Docs Menu
Docs Home
/
MongoDB Atlas
/ / /

How to Run $lookup with an Atlas Search $search Query

On this page

  • Create the Atlas Search Index
  • Run $lookup with $search to Search the Collections

Starting in v6.0, the MongoDB $lookup aggregation stage supports $search inside the $lookup pipeline option. Using $lookup, you can join multiple collections in the same database at query-time and run a $search query to further narrow down your search.

Note

$lookup queries are not very performant because Atlas Search does a full document lookup on the database for each document in the collection. To learn more, see Reduce $lookup Operations.

This tutorial demonstrates how to run a $lookup query with $search against the accounts and customers collections in the sample_analytics database. It takes you through the following steps:

  1. Set up an Atlas Search index with dynamic mapping for the accounts collection in the sample_analytics database.

  2. Run $lookup query with $search to find customers from the customers collections whose accounts have purchased both CurrencyService and InvestmentStock products in the accounts collection.

Before you begin, ensure that your Atlas cluster meets the requirements described in the Prerequisites.

Note

To run $lookup query with $search, your cluster must run MongoDB v6.0 or later. If not, Atlas Search displays the following error message:

$_internalSearchMongotRemote is not allowed within a $lookup's sub-pipeline.

To learn more, see Upgrade Major MongoDB Version for a Cluster.

To create an Atlas Search index, you must have Project Data Access Admin or higher access to the project.

Create an Atlas Search index named lookup-with-search-tutorial on all the fields in the sample_analytics.accounts collection.

1
  1. If it is not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.

  2. If it is not already displayed, select your desired project from the Projects menu in the navigation bar.

  3. If the Clusters page is not already displayed, click Database in the sidebar.

2

You can go the Atlas Search page from the sidebar, the Data Explorer, or your cluster details page.

  1. In the sidebar, click Atlas Search under the Services heading.

  2. From the Select data source dropdown, select your cluster and click Go to Atlas Search.

  1. Click the Browse Collections button for your cluster.

  2. Expand the database and select the collection.

  3. Click the Search Indexes tab for the collection.

  1. Click the cluster's name.

  2. Click the Atlas Search tab.

3

Click Create Search Index.

4
  • For a guided experience, select the Atlas Search Visual Editor.

  • To edit the raw index definition, select the Atlas Search JSON Editor.

5
  1. In the Index Name field, enter lookup-with-search-tutorial.

    Note

    If you name your index default, you don't need to specify an index parameter when using the $search pipeline stage. Otherwise, you must specify the index name using the index parameter.

  2. In the Database and Collection section, find the sample_analytics database, and select the accounts collection.

6

The following index definition dynamically indexes the fields of supported types in the collection. You can use the Atlas Search Visual Editor or the Atlas Search JSON Editor in the Atlas user interface to create the index.

  1. Click Next.

  2. Review the default index definition for the collection.

  1. Click Next.

  2. Review the index definition.

    Your index definition should look similar to the following:

    {
    "mappings": {
    "dynamic": true
    }
    }
  3. Click Next.

7
8

A modal window displays to let you know your index is building. Click the Close button.

9

The index should take about one minute to build. While it is building, the Status column reads Build in Progress. When it is finished building, the Status column reads Active.


➤ Use the Select your language drop-down menu on this page to set the language of the examples in this section.


Connect to your Atlas cluster and run the sample query against the indexed collections in the sample_analytics database.

1

Open mongosh in a terminal window and connect to your cluster. For detailed instructions on connecting, see Connect via mongosh.

2

Run the following command at mongosh prompt:

use sample_analytics
switched to db sample_analytics
3

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

db.customers.aggregate([
{
$lookup:{
"from": "accounts",
"localField": "accounts",
"foreignField": "account_id",
"as": "purchases",
"pipeline": [{
"$search": {
"index": "lookup-with-search-tutorial",
"compound": {
"must": [{
"queryString": {
"defaultPath": "products",
"query": "products: (CurrencyService AND InvestmentStock)"
}
}],
"should": [{
"range": {
"path": "limit",
"gte": 5000,
"lte": 10000
}
}]
}
}
},{
"$project": {
"_id": 0
}
}]
}
},{
"$limit": 5
},{
"$project": {
"_id": 0,
"address": 0,
"birthdate": 0,
"username": 0,
"tier_and_details": 0
}
}
])
[
{
name: 'Elizabeth Ray',
email: 'arroyocolton@gmail.com',
active: true,
accounts: [ 371138, 324287, 276528, 332179, 422649, 387979 ],
purchases: [
{
account_id: 422649,
limit: 10000,
products: [ 'CurrencyService', 'InvestmentStock' ]
},
{
account_id: 324287,
limit: 10000,
products: [
'Commodity',
'CurrencyService',
'Derivatives',
'InvestmentStock'
]
},
{
account_id: 332179,
limit: 10000,
products: [
'Commodity',
'CurrencyService',
'InvestmentFund',
'Brokerage',
'InvestmentStock'
]
}
]
},
{
name: 'Lindsay Cowan',
email: 'cooperalexis@hotmail.com',
accounts: [ 116508 ],
purchases: []
},
{
name: 'Katherine David',
email: 'timothy78@hotmail.com',
accounts: [ 462501, 228290, 968786, 515844, 377292 ],
purchases: [
{
account_id: 228290,
limit: 10000,
products: [
'CurrencyService',
'InvestmentStock',
'InvestmentFund',
'Brokerage'
]
},
{
account_id: 515844,
limit: 10000,
products: [
'Commodity',
'CurrencyService',
'InvestmentFund',
'Brokerage',
'InvestmentStock'
]
}
]
},
{
name: 'Leslie Martinez',
email: 'tcrawford@gmail.com',
accounts: [ 170945, 951849 ],
purchases: []
},
{
name: 'Brad Cardenas',
email: 'dustin37@yahoo.com',
accounts: [ 721914, 817222, 973067, 260799, 87389 ],
purchases: [
{
account_id: 87389,
limit: 10000,
products: [ 'CurrencyService', 'InvestmentStock' ]
},
{
account_id: 260799,
limit: 10000,
products: [
'Brokerage',
'InvestmentStock',
'Commodity',
'CurrencyService'
]
}
]
}
]
1

Open MongoDB Compass and connect to your cluster. For detailed instructions on connecting, see Connect via Compass.

2

On the Database screen, click the sample_analytics database and then click the customers collection.

3

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

To run this query in MongoDB Compass:

  1. Click the Aggregations tab.

  2. Click Select..., then configure each of the following pipeline stages by selecting the stage from the dropdown and adding the query for that stage. Click Add Stage to add additional stages.

    Pipeline Stage
    Query
    $lookup
    {
    from: "accounts",
    localField: "accounts",
    foreignField: "account_id",
    as: "purchases",
    pipeline: [
    {
    $search: {
    index: "lookup-with-search-tutorial",
    compound: {
    must: [
    {
    queryString: {
    defaultPath: "products",
    query:
    "products: (CurrencyService AND InvestmentStock)"
    }
    }
    ],
    should: [
    {
    range: {
    path: "limit",
    gte: 5000,
    lte: 10000,
    }
    }
    ]
    }
    }
    },
    {
    $project: {
    _id: 0,
    }
    }
    ]
    }
    $limit
    5
    $project
    {
    _id: 0,
    address: 0,
    birthdate: 0,
    username: 0,
    tier_and_details: 0,
    }

    If you enabled Auto Preview, MongoDB Compass displays the following documents next to the $project pipeline stage:

    name: Elizabeth Ray
    email: arroyocolton@gmail.com
    active: True
    accounts: Array (6)
    purchases: Array (3)
    name: "Lindsay Cowan"
    email: "cooperalexis@hotmail.com"
    accounts: Array (1)
    purchases: Array (empty)
    name: "Katherine David"
    email: "timothy78@hotmail.com"
    accounts: Array (5)
    urchases: Array (2)
    name: "Leslie Martinez"
    email: "tcrawford@gmail.com"
    accounts: Array (2)
    purchases: Array (empty)
    name: "Brad Cardenas"
    email: "dustin37@yahoo.com"
    accounts: Array (5)
    purchases: Array (2)
4

MongoDB Compass might not display all the fields inside objects and all the values inside arrays for the documents it returns in the results. To view all the fields and values, expand the field in the results.

1
  1. Create a new directory called lookup-with-search and initialize your project with the dotnet new command.

    mkdir lookup-with-search
    cd lookup-with-search
    dotnet new console
  2. Add the .NET/C# Driver to your project as a dependency.

    dotnet add package MongoDB.Driver
2

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

1using MongoDB.Bson;
2using MongoDB.Bson.Serialization.Attributes;
3using MongoDB.Bson.Serialization.Conventions;
4using MongoDB.Driver;
5using MongoDB.Driver.Core;
6using MongoDB.Driver.Search;
7
8public class LookupWithSearch{
9
10 static void Main(string[] args) {// allow automapping of the camelCase database fields to our MovieDocument
11 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
12 ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
13
14 // connect to your Atlas cluster
15 var mongoClient = new MongoClient("<connection-string>");
16
17 // define namespace
18 var analyticsDatabase = mongoClient.GetDatabase("sample_analytics");
19 var accountsCollection = analyticsDatabase.GetCollection<AccountDocument>("accounts");
20 var customersCollection = analyticsDatabase.GetCollection<CustomerDocument>("customers");
21
22 // define pipeline stages
23 var lookupStage = new BsonDocument("$lookup", new BsonDocument{
24 { "from", "accounts" }, { "localField", "accounts" }, { "foreignField", "account_id" },
25 { "as", "purchases" }, { "pipeline", new BsonArray{
26 new BsonDocument("$search", new BsonDocument{
27 { "index", "lookup-with-search-tutorial" }, { "compound", new BsonDocument{
28 { "must", new BsonArray{
29 new BsonDocument("queryString", new BsonDocument{
30 { "defaultPath", "products" }, { "query", "products: (CurrencyService AND InvestmentStock)" }
31 })
32 }},
33 { "should", new BsonArray{
34 new BsonDocument("range", new BsonDocument{
35 { "path", "limit" }, { "gte", 5000 }, { "lte", 10000 }
36 })
37 }}
38 }}
39 })
40 }}
41 });
42 var projectStage1 = new BsonDocument("$project", new BsonDocument("_id", 0));
43 var limitStage = new BsonDocument("$limit", 5);
44 var projectStage2 = new BsonDocument("$project", new BsonDocument{
45 { "_id", 0 }, { "address", 0 }, { "birthdate", 0 }, { "username", 0 }, { "tier_and_details", 0 }
46 });
47 var aggregationPipeline = new List<BsonDocument> {lookupStage, projectStage1, limitStage, projectStage2};
48
49 // run pipeline
50 var results = customersCollection.Aggregate<BsonDocument>(aggregationPipeline).ToList();
51
52 // print results
53 foreach (var acct in results) {
54 Console.WriteLine(acct.ToJson());
55 }
56 }
57}
58
59// define fields in the accounts collection
60[BsonIgnoreExtraElements]
61public class AccountDocument {
62 [BsonId]
63 [BsonRepresentation(BsonType.ObjectId)]
64 [BsonElement("_id")]
65 public string Id { get; set; }
66
67 [BsonElement("account_id")]
68 public int AccountId { get; set; }
69
70 [BsonElement("limit")]
71 public int Limit { get; set; }
72}
73
74// define fields in the customers collection
75[BsonIgnoreExtraElements]
76public class CustomerDocument {
77 [BsonId]
78 [BsonRepresentation(BsonType.ObjectId)]
79 [BsonElement("_id")]
80 public ObjectId Id { get; set; }
81
82 [BsonElement("name")]
83 public string Name { get; set; }
84
85 [BsonElement("email")]
86 public string Email { get; set; }
87
88 [BsonElement("active")]
89 public bool Active { get; set; }
90
91 [BsonElement("accounts")]
92 public List<int> Accounts { get; set; }
93}
94
95// define new array field for matching documents
96public class CustomerLookedUp: CustomerDocument{
97 public List<CustomerDocument> Purchases { get; set; }
98}
3

Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

4
dotnet run lookup-with-search.csproj
{
"name" : "Elizabeth Ray",
"email" : "arroyocolton@gmail.com",
"active" : true,
"accounts" : [371138, 324287, 276528, 332179, 422649,
387979],
"purchases" : [
{
"_id" : ObjectId("5ca4bbc7a2dd94ee58162402"),
"account_id" : 422649,
"limit" : 10000,
"products" : ["CurrencyService", "InvestmentStock"]
},
{
"_id" : ObjectId("5ca4bbc7a2dd94ee581623a9"),
"account_id" : 324287,
"limit" : 10000,
"products" : ["Commodity", "CurrencyService", "Derivatives", "InvestmentStock"]
},
{
"_id" : ObjectId("5ca4bbc7a2dd94ee58162400"),
"account_id" : 332179,
"limit" : 10000,
"products" : ["Commodity", "CurrencyService", "InvestmentFund", "Brokerage", "InvestmentStock"]
}
]
}
{
"name" : "Lindsay Cowan",
"email" : "cooperalexis@hotmail.com",
"accounts" : [116508],
"purchases" : []
}
{
"name" : "Katherine David",
"email" : "timothy78@hotmail.com",
"accounts" : [462501, 228290, 968786, 515844, 377292],
"purchases" : [
{
"_id" : ObjectId("5ca4bbc7a2dd94ee581623c9"),
"account_id" : 228290,
"limit" : 10000,
"products" : ["CurrencyService", "InvestmentStock", "InvestmentFund", "Brokerage"] },
{
"_id" : ObjectId("5ca4bbc7a2dd94ee581623cb"),
"account_id" : 515844,
"limit" : 10000,
"products" : ["Commodity", "CurrencyService", "InvestmentFund", "Brokerage", "InvestmentStock"]
}
]
}
{
"name" : "Leslie Martinez",
"email" : "tcrawford@gmail.com",
"accounts" : [170945, 951849],
"purchases" : []
}
{
"name" : "Brad Cardenas",
"email" : "dustin37@yahoo.com",
"accounts" : [721914, 817222, 973067, 260799, 87389],
"purchases" : [
{
"_id" : ObjectId("5ca4bbc7a2dd94ee581623d6"),
"account_id" : 87389,
"limit" : 10000,
"products" : ["CurrencyService", "InvestmentStock"] },
{
"_id" : ObjectId("5ca4bbc7a2dd94ee581623d5"),
"account_id" : 260799,
"limit" : 10000,
"products" : ["Brokerage", "InvestmentStock", "Commodity", "CurrencyService"]
}
]
}
1
2

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

1package main
2import (
3 "context"
4 "fmt"
5 "time"
6
7 "go.mongodb.org/mongo-driver/bson"
8 "go.mongodb.org/mongo-driver/mongo"
9 "go.mongodb.org/mongo-driver/mongo/options"
10)
11
12func main() {
13 var err error
14 // connect to the Atlas cluster
15 ctx := context.Background()
16 client, err := mongo.Connect(ctx, options.Client().ApplyURI("<connection-string>"))
17 if err != nil {
18 panic(err)
19 }
20 defer client.Disconnect(ctx)
21 // set namespace
22 collection := client.Database("sample_analytics").Collection("customers")
23 // define pipeline
24 lookupStage := bson.D{{"$lookup", bson.D{
25 {"from", "accounts"},
26 {"localField", "accounts"},
27 {"foreignField", "account_id"},
28 {"as", "purchases"},
29 {"pipeline", bson.A{
30 bson.D{
31 {"$search", bson.D{
32 {"index", "lookup-with-search-tutorial"},
33 {"compound", bson.D{
34 {"must", bson.A{
35 bson.D{{"queryString", bson.D{
36 {"defaultPath", "products"},
37 {"query", "products: (CurrencyService AND InvestmentStock)"},
38 }}},
39 }},
40 {"should", bson.A{
41 bson.D{{"range", bson.D{
42 {"path", "limit"},
43 {"gte", 5000},
44 {"lte", 10000},
45 }}},
46 }},
47 }},
48 }},
49 },
50 bson.D{{"$project", bson.D{
51 {"_id", 0},
52 {"address", 0},
53 {"birthdate", 0},
54 {"username", 0},
55 {"tier_and_details", 0},
56 }}},
57 }},
58 }}}
59 limitStage := bson.D{{"$limit", 5}}
60 projectStage := bson.D{{"$project", bson.D{
61 {"name", 1},
62 {"email", 1},
63 {"active", 1},
64 {"accounts", 1},
65 {"purchases", 1},
66 }}}
67 // specify the amount of time the operation can run on the server
68 opts := options.Aggregate().SetMaxTime(5 * time.Second)
69 // run pipeline
70 cursor, err := collection.Aggregate(ctx, mongo.Pipeline{lookupStage, limitStage, projectStage}, opts)
71 if err != nil {
72 panic(err)
73 }
74 // print results
75 var results []bson.D
76 if err = cursor.All(context.TODO(), &results); err != nil {
77 panic(err)
78 }
79 for _, result := range results {
80 fmt.Println(result)
81 }
82}
3

Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

4
go run lookup-with-search-query.go
[{_id ObjectID("5ca4bbcea2dd94ee58162a68")} {name Elizabeth Ray} {email arroyocolton@gmail.com} {active true} {accounts [371138 324287 276528 332179 422649 387979]} {purchases [[{account_id 422649} {limit 10000} {products [CurrencyService InvestmentStock]}] [{account_id 324287} {limit 10000} {products [Commodity CurrencyService Derivatives InvestmentStock]}] [{account_id 332179} {limit 10000} {products [Commodity CurrencyService InvestmentFund Brokerage InvestmentStock]}]]}]
[{_id ObjectID("5ca4bbcea2dd94ee58162a69")} {name Lindsay Cowan} {email cooperalexis@hotmail.com} {accounts [116508]} {purchases []}]
[{_id ObjectID("5ca4bbcea2dd94ee58162a6a")} {name Katherine David} {email timothy78@hotmail.com} {accounts [462501 228290 968786 515844 377292]} {purchases [[{account_id 228290} {limit 10000} {products [CurrencyService InvestmentStock InvestmentFund Brokerage]}] [{account_id 515844} {limit 10000} {products [Commodity CurrencyService InvestmentFund Brokerage InvestmentStock]}]]}]
[{_id ObjectID("5ca4bbcea2dd94ee58162a6b")} {name Leslie Martinez} {email tcrawford@gmail.com} {accounts [170945 951849]} {purchases []}]
[{_id ObjectID("5ca4bbcea2dd94ee58162a6c")} {name Brad Cardenas} {email dustin37@yahoo.com} {accounts [721914 817222 973067 260799 87389]} {purchases [[{account_id 87389} {limit 10000} {products [CurrencyService InvestmentStock]}] [{account_id 260799} {limit 10000} {products [Brokerage InvestmentStock Commodity CurrencyService]}]]}]
1
junit
4.11 or higher version
mongodb-driver-sync
4.3.0 or higher version
slf4j-log4j12
1.7.30 or higher version
2
3

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

1import static com.mongodb.client.model.Aggregates.limit;
2import static com.mongodb.client.model.Aggregates.project;
3import static com.mongodb.client.model.Projections.*;
4import java.util.Arrays;
5import com.mongodb.client.MongoClient;
6import com.mongodb.client.MongoClients;
7import com.mongodb.client.MongoCollection;
8import com.mongodb.client.MongoDatabase;
9import org.bson.Document;
10
11public class LookupWithSearchQuery {
12
13 public static void main(String[] args) {
14 // connect to your Atlas cluster
15 String uri = "<connection-string>";
16
17 try (MongoClient mongoClient = MongoClients.create(uri)) {
18 // set namespace
19 MongoDatabase database = mongoClient.getDatabase("sample_analytics");
20 MongoCollection<Document> collection = database.getCollection("customers");
21
22 // define pipeline
23 Document agg = new Document("$lookup",
24 new Document("from", "accounts")
25 .append("localField", "accounts")
26 .append("foreignField", "account_id")
27 .append("as", "purchases")
28 .append("pipeline", Arrays.asList(new Document("$search",
29 new Document("index", "lookup-with-search-tutorial")
30 .append("compound",
31 new Document("must", Arrays.asList(new Document("queryString",
32 new Document("defaultPath", "products")
33 .append("query", "products: (CurrencyService AND InvestmentStock)"))))
34 .append("should", Arrays.asList(new Document("range",
35 new Document("path", "limit")
36 .append("gte", 5000L)
37 .append("lte", 10000L)
38 )))
39 )
40 ),
41 new Document("$limit", 5L),
42 new Document("$project",
43 new Document("_id", 0L)
44 .append("address", 0L)
45 .append("birthdate", 0L)
46 .append("username", 0L)
47 .append("tier_and_details", 0L)
48 )))
49 );
50 // run pipeline and print results
51 collection.aggregate(Arrays.asList(agg,
52 limit(5),
53 project(fields(excludeId(), include("name", "email", "active", "accounts", "purchases")))
54 ))
55 .forEach(doc -> System.out.println(doc.toJson()));
56 }
57 }
58}

Note

To run the sample code in your Maven environment, add the following code above the import statements in your file.

package com.mongodb.drivers;
4

Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

5
javac LookupWithSearchQuery.java
java LookupWithSearchQuery
{"name": "Elizabeth Ray", "email": "arroyocolton@gmail.com", "active": true, "accounts": [371138, 324287, 276528, 332179, 422649, 387979], "purchases": [{"account_id": 422649, "limit": 10000, "products": ["CurrencyService", "InvestmentStock"]}, {"account_id": 324287, "limit": 10000, "products": ["Commodity", "CurrencyService", "Derivatives", "InvestmentStock"]}, {"account_id": 332179, "limit": 10000, "products": ["Commodity", "CurrencyService", "InvestmentFund", "Brokerage", "InvestmentStock"]}]}
{"name": "Lindsay Cowan", "email": "cooperalexis@hotmail.com", "accounts": [116508], "purchases": []}
{"name": "Katherine David", "email": "timothy78@hotmail.com", "accounts": [462501, 228290, 968786, 515844, 377292], "purchases": [{"account_id": 228290, "limit": 10000, "products": ["CurrencyService", "InvestmentStock", "InvestmentFund", "Brokerage"]}, {"account_id": 515844, "limit": 10000, "products": ["Commodity", "CurrencyService", "InvestmentFund", "Brokerage", "InvestmentStock"]}]}
{"name": "Leslie Martinez", "email": "tcrawford@gmail.com", "accounts": [170945, 951849], "purchases": []}
{"name": "Brad Cardenas", "email": "dustin37@yahoo.com", "accounts": [721914, 817222, 973067, 260799, 87389], "purchases": [{"account_id": 87389, "limit": 10000, "products": ["CurrencyService", "InvestmentStock"]}, {"account_id": 260799, "limit": 10000, "products": ["Brokerage", "InvestmentStock", "Commodity", "CurrencyService"]}]}
1
mongodb-driver-kotlin-coroutine
4.10.0 or higher version
2
3

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

1import com.mongodb.client.model.Aggregates.limit
2import com.mongodb.client.model.Aggregates.project
3import com.mongodb.client.model.Projections.*
4import com.mongodb.kotlin.client.coroutine.MongoClient
5import kotlinx.coroutines.runBlocking
6import org.bson.Document
7import java.util.*
8
9fun main() {
10 // connect to your Atlas cluster
11 val uri = "<connection-string>"
12 val mongoClient = MongoClient.create(uri)
13
14 // set namespace
15 val database = mongoClient.getDatabase("sample_analytics")
16 val collection = database.getCollection<Document>("customers")
17
18 runBlocking {
19 // define pipeline
20 val agg = Document(
21 "\$lookup",
22 Document("from", "accounts")
23 .append("localField", "accounts")
24 .append("foreignField", "account_id")
25 .append("as", "purchases")
26 .append(
27 "pipeline", Arrays.asList(
28 Document(
29 "\$search",
30 Document("index", "lookup-with-search-tutorial")
31 .append(
32 "compound",
33 Document(
34 "must", Arrays.asList(
35 Document(
36 "queryString",
37 Document("defaultPath", "products")
38 .append("query", "products: (CurrencyService AND InvestmentStock)")
39 )
40 )
41 )
42 .append(
43 "should", Arrays.asList(
44 Document(
45 "range",
46 Document("path", "limit")
47 .append("gte", 5000)
48 .append("lte", 10000)
49 )
50 )
51 )
52 )
53 ),
54 Document("\$limit", 5),
55 Document(
56 "\$project",
57 Document("_id", 0)
58 .append("address", 0)
59 .append("birthdate", 0)
60 .append("username", 0)
61 .append("tier_and_details", 0)
62 )
63 )
64 )
65 )
66
67 // run pipeline and print results
68 val resultsFlow = collection.aggregate<Document>(
69 listOf(
70 agg,
71 limit(5),
72 project(fields(excludeId(), include("name", "email", "active", "accounts", "purchases")))
73 )
74 )
75 resultsFlow.collect { println(it) }
76 }
77 mongoClient.close()
78}
4

Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

5

When you run the LookupWithSearchQuery.kt program in your IDE, it prints the following documents:

Document{{name=Elizabeth Ray, email=arroyocolton@gmail.com, active=true, accounts=[371138, 324287, 276528, 332179, 422649, 387979], purchases=[Document{{account_id=422649, limit=10000, products=[CurrencyService, InvestmentStock]}}, Document{{account_id=324287, limit=10000, products=[Commodity, CurrencyService, Derivatives, InvestmentStock]}}, Document{{account_id=332179, limit=10000, products=[Commodity, CurrencyService, InvestmentFund, Brokerage, InvestmentStock]}}]}}
Document{{name=Lindsay Cowan, email=cooperalexis@hotmail.com, accounts=[116508], purchases=[]}}
Document{{name=Katherine David, email=timothy78@hotmail.com, accounts=[462501, 228290, 968786, 515844, 377292], purchases=[Document{{account_id=228290, limit=10000, products=[CurrencyService, InvestmentStock, InvestmentFund, Brokerage]}}, Document{{account_id=515844, limit=10000, products=[Commodity, CurrencyService, InvestmentFund, Brokerage, InvestmentStock]}}]}}
Document{{name=Leslie Martinez, email=tcrawford@gmail.com, accounts=[170945, 951849], purchases=[]}}
Document{{name=Brad Cardenas, email=dustin37@yahoo.com, accounts=[721914, 817222, 973067, 260799, 87389], purchases=[Document{{account_id=87389, limit=10000, products=[CurrencyService, InvestmentStock]}}, Document{{account_id=260799, limit=10000, products=[Brokerage, InvestmentStock, Commodity, CurrencyService]}}]}}
1
2

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

1const MongoClient = require("mongodb").MongoClient;
2const assert = require("assert");
3
4const agg = [
5 {
6 '$lookup': {
7 'from': 'accounts',
8 'localField': 'accounts',
9 'foreignField': 'account_id',
10 'as': 'purchases',
11 'pipeline': [
12 {
13 '$search': {
14 'index': 'lookup-with-search-tutorial',
15 'compound': {
16 'must': [
17 {
18 'queryString': {
19 'defaultPath': 'products',
20 'query': 'products: (CurrencyService AND InvestmentStock)'
21 }
22 }
23 ],
24 'should': [
25 {
26 'range': {
27 'path': 'limit',
28 'gte': 5000,
29 'lte': 10000
30 }
31 }
32 ]
33 }
34 }
35 }, {
36 '$project': {
37 '_id': 0
38 }
39 }
40 ]
41 }
42 }, {
43 '$limit': 5
44 }, {
45 '$project': {
46 '_id': 0,
47 'address': 0,
48 'birthdate': 0,
49 'username': 0,
50 'tier_and_details': 0
51 }
52 }
53 ];
54
55MongoClient.connect(
56 "<connection-string>",
57 { useNewUrlParser: true, useUnifiedTopology: true },
58 async function (connectErr, client) {
59 assert.equal(null, connectErr);
60 const coll = client.db("sample_analytics").collection("customers");
61 let cursor = await coll.aggregate(agg);
62 await cursor.forEach((doc) => console.log(doc));
63 client.close();
64 }
65);
3

Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

4

Run the following command to query your collection:

node lookup-with-search-query.js
{
name: 'Elizabeth Ray',
email: 'arroyocolton@gmail.com',
active: true,
accounts: [ 371138, 324287, 276528, 332179, 422649, 387979 ],
purchases: [
{ account_id: 422649, limit: 10000, products: [Array] },
{ account_id: 324287, limit: 10000, products: [Array] },
{ account_id: 332179, limit: 10000, products: [Array] }
]
}
{
name: 'Lindsay Cowan',
email: 'cooperalexis@hotmail.com',
accounts: [ 116508 ],
purchases: []
}
{
name: 'Katherine David',
email: 'timothy78@hotmail.com',
accounts: [ 462501, 228290, 968786, 515844, 377292 ],
purchases: [
{ account_id: 228290, limit: 10000, products: [Array] },
{ account_id: 515844, limit: 10000, products: [Array] }
]
}
{
name: 'Leslie Martinez',
email: 'tcrawford@gmail.com',
accounts: [ 170945, 951849 ],
purchases: []
}
{
name: 'Brad Cardenas',
email: 'dustin37@yahoo.com',
accounts: [ 721914, 817222, 973067, 260799, 87389 ],
purchases: [
{ account_id: 87389, limit: 10000, products: [Array] },
{ account_id: 260799, limit: 10000, products: [Array] }
]
}
1
2

The following query uses the following stages:

  • $lookup to do the following:

    • Join customers and accounts collections in the sample_analytics database based on the account ID of the customers and return the matching documents from the accounts collection in an array field named purchases.

    • Use $search stage in the sub-pipeline to search for customer accounts that must have purchased both CurrencyService and InvestmentStock with preference for an order limit between 5000 to 10000.

  • $limit stage to limit the output to 5 results.

  • $project stage to exclude the specified fields in the results.

1import datetime
2import pymongo
3
4# connect to your Atlas cluster
5client = pymongo.MongoClient('<connection-string>')
6
7# define pipeline
8pipeline = [
9 {
10 '$lookup': {
11 'from': 'accounts',
12 'localField': 'accounts',
13 'foreignField': 'account_id',
14 'as': 'purchases',
15 'pipeline': [
16 {
17 '$search': {
18 'index': 'lookup-with-search-tutorial',
19 'compound': {
20 'must': [
21 {
22 'queryString': {
23 'defaultPath': 'products',
24 'query': 'products: (CurrencyService AND InvestmentStock)'
25 }
26 }
27 ],
28 'should': [
29 {
30 'range': {
31 'path': 'limit',
32 'gte': 5000,
33 'lte': 10000
34 }
35 }
36 ]
37 }
38 }
39 },
40 { '$project': { '_id': 0 } }
41 ]
42 }
43 },
44 { '$limit': 5 },
45 {
46 '$project': {
47 '_id': 0,
48 'address': 0,
49 'birthdate': 0,
50 'username': 0,
51 'tier_and_details': 0
52 }
53 }
54]
55
56# run pipeline
57result = client['sample_analytics']['customers'].aggregate(pipeline)
58
59# print results
60for i in result:
61 print(i)
3

Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

4
python lookup-with-search-query.py
{'name': 'Elizabeth Ray', 'email': 'arroyocolton@gmail.com', 'active': True, 'accounts': [371138, 324287, 276528, 332179, 422649, 387979], 'purchases': [{'account_id': 422649, 'limit': 10000, 'products': ['CurrencyService', 'InvestmentStock']}, {'account_id': 324287, 'limit': 10000, 'products': ['Commodity', 'CurrencyService', 'Derivatives', 'InvestmentStock']}, {'account_id': 332179, 'limit': 10000, 'products': ['Commodity', 'CurrencyService', 'InvestmentFund', 'Brokerage', 'InvestmentStock']}]}
{'name': 'Lindsay Cowan', 'email': 'cooperalexis@hotmail.com', 'accounts': [116508], 'purchases': []}
{'name': 'Katherine David', 'email': 'timothy78@hotmail.com', 'accounts': [462501, 228290, 968786, 515844, 377292], 'purchases': [{'account_id': 228290, 'limit': 10000, 'products': ['CurrencyService', 'InvestmentStock', 'InvestmentFund', 'Brokerage']}, {'account_id': 515844, 'limit': 10000, 'products': ['Commodity', 'CurrencyService', 'InvestmentFund', 'Brokerage', 'InvestmentStock']}]}
{'name': 'Leslie Martinez', 'email': 'tcrawford@gmail.com', 'accounts': [170945, 951849], 'purchases': []}
{'name': 'Brad Cardenas', 'email': 'dustin37@yahoo.com', 'accounts': [721914, 817222, 973067, 260799, 87389], 'purchases': [{'account_id': 87389, 'limit': 10000, 'products': ['CurrencyService', 'InvestmentStock']}, {'account_id': 260799, 'limit': 10000, 'products': ['Brokerage', 'InvestmentStock', 'Commodity', 'CurrencyService']}]}

Back

Materialized Views

Next

$unionWith with $search