How to Run $unionWith
with an Atlas Search $search
Query
Starting in v6.0, the MongoDB $unionWith
aggregation stage
supports $search
inside the $unionWith
pipeline
option. Using $unionWith
, you can combine
$search
results from multiple collections in the same
database in the result set.
This tutorial demonstrates how to run a $unionWith
query
with $search
against the companies
and inspections
collections in the sample_training
database. It takes you through
the following steps:
Set up an Atlas Search index with dynamic mappings for the
companies
andinspections
collections in thesample_training
database.Run
$unionWith
query with$search
to perform a union of companies withmobile
in their name from thecompanies
collection with companies with same or similar business name in theinspections
collection.
Before you begin, ensure that your Atlas cluster meets the requirements described in the Prerequisites.
Note
To run a $unionWith
query with $search
, your
cluster must run MongoDB v6.0 or higher.
To create an Atlas Search index, you must have Project Data Access Admin
or higher access to the project.
Create the Atlas Search Indexes
In this section, you will create an Atlas Search index named default
on
all the fields in the companies
collection in the
sample_training
database. You will create another Atlas Search index
named default
on all the fields in the inspections
collection in the sample_training
database. You must perform the
following steps for each collection.
In Atlas, go to the Clusters page for your project.
If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.
If it's not already displayed, select your desired project from the Projects menu in the navigation bar.
If it's not already displayed, click Clusters in the sidebar.
The Clusters page displays.
Go to the Atlas Search page for your cluster.
You can go the Atlas Search page from the sidebar, the Data Explorer, or your cluster details page.
In the sidebar, click Atlas Search under the Services heading.
From the Select data source dropdown, select your cluster and click Go to Atlas Search.
The Atlas Search page displays.
Click the Browse Collections button for your cluster.
Expand the database and select the collection.
Click the Search Indexes tab for the collection.
The Atlas Search page displays.
Click the cluster's name.
Click the Atlas Search tab.
The Atlas Search page displays.
Enter the Index Name, and set the Database and Collection.
In the Index Name field, enter
default
.If you name your index
default
, you don't need to specify anindex
parameter in the $search pipeline stage. If you give a custom name to your index, you must specify this name in theindex
parameter.In the Database and Collection section, find the
sample_training
database, and select the collection.To create an index for the
companies
collection, selectcompanies
.To create an index for the
inspections
collection, selectinspections
.
Specify an index definition.
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.
Click Next.
Review the
"default"
index definition for the collection.
Click Next.
Review the index definition.
Your index definition should look similar to the following example:
{ "mappings": { "dynamic": true } }
Run $unionWith
with $search
to Search the Collections
➤ Use the Select your language drop-down menu to set the language of the example in this section.
In this section, you will connect to your Atlas cluster and run
the sample query against the indexed collections in the
sample_training
database.
Connect to your cluster in mongosh
.
Open mongosh
in a terminal window and connect to your
cluster. For detailed instructions on connecting, see
Connect via mongosh
.
Switch to the sample_training
database.
Run the following command at mongosh
prompt:
use sample_training
switched to db sample_training
Run the following $unionWith
with an Atlas Search $search
query.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
db.companies.aggregate([ { "$search": { "text": { "query": "Mobile", "path": "name" } } }, { "$project": { "score": { "$meta": "searchScore" }, "_id": 0, "number_of_employees": 1, "founded_year": 1, "name": 1 } }, { "$set": { "source": "companies" } }, { "$limit": 3 }, { "$unionWith": { "coll": "inspections", "pipeline": [ { "$search": { "text": { "query": "Mobile", "path": "business_name" } } }, { "$set": { "source": "inspections" } }, { "$project": { "score": { "$meta": "searchScore" }, "source": 1, "_id": 0, "business_name": 1, "address": 1 } }, { "$limit": 3 }, { "$sort": { "score": -1 } } ] } } ])
[ { name: 'XLR8 Mobile', number_of_employees: 21, founded_year: 2006, score: 2.0815043449401855, source: 'companies' }, { name: 'Pulse Mobile', number_of_employees: null, founded_year: null, score: 2.0815043449401855, source: 'companies' }, { name: 'T-Mobile', number_of_employees: null, founded_year: null, score: 2.0815043449401855, source: 'companies' }, { business_name: 'T. MOBILE', address: { city: 'BROOKLYN', zip: 11209, street: '86TH ST', number: 440 }, score: 2.900916337966919, source: 'inspections' }, { business_name: 'BOOST MOBILE', address: { city: 'BRONX', zip: 10458, street: 'E FORDHAM RD', number: 261 }, score: 2.900916337966919, source: 'inspections' }, { business_name: 'SPRING MOBILE', address: { city: 'SOUTH RICHMOND HILL', zip: 11419, street: 'LIBERTY AVE', number: 12207 }, score: 2.900916337966919, source: 'inspections' } ]
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
db.companies.aggregate([ { "$search": { "text": { "query": "mobile", "path": "name", "score": { "boost": { "value": 1.6 } } } } }, { "$project": { "score": { "$meta": "searchScore" }, "_id": 0, "number_of_employees": 1, "founded_year": 1, "name": 1 } }, { "$addFields": { "source": "companies", "source_count": "$$SEARCH_META.count.lowerBound" } }, { "$limit": 3 }, { "$unionWith": { "coll": "inspections", "pipeline": [ { "$search": { "text": { "query": "mobile", "path": "business_name" } } }, { "$project": { "score": { "$meta": "searchScore" }, "business_name": 1, "address": 1, "_id": 0 } }, { "$limit": 3 }, { "$set": { "source": "inspections", "source_count": "$$SEARCH_META.count.lowerBound" } }, { "$sort": { "score": -1 } } ] } }, { "$facet": { "allDocs": [], "totalCount": [ { "$group": { "_id": "$source", "firstCount": { "$first": "$source_count" } } }, { "$project": { "totalCount": { "$sum": "$firstCount" } } } ] } } ])
[ { allDocs: [ { name: 'XLR8 Mobile', number_of_employees: 21, founded_year: 2006, score: 3.33040714263916, source: 'companies', source_count: Long("52") }, { name: 'Pulse Mobile', number_of_employees: null, founded_year: null, score: 3.33040714263916, source: 'companies', source_count: Long("52") }, { name: 'T-Mobile', number_of_employees: null, founded_year: null, score: 3.33040714263916, source: 'companies', source_count: Long("52") }, { business_name: 'T. MOBILE', address: { city: 'BROOKLYN', zip: 11209, street: '86TH ST', number: 440 }, score: 2.900916337966919, source: 'inspections', source_count: Long("456") }, { business_name: 'BOOST MOBILE', address: { city: 'BRONX', zip: 10458, street: 'E FORDHAM RD', number: 261 }, score: 2.900916337966919, source: 'inspections', source_count: Long("456") }, { business_name: 'SPRING MOBILE', address: { city: 'SOUTH RICHMOND HILL', zip: 11419, street: 'LIBERTY AVE', number: 12207 }, score: 2.900916337966919, source: 'inspections', source_count: Long("456") } ], totalCount: [ { _id: 'companies', totalCount: Long("52") }, { _id: 'inspections', totalCount: Long("456") } ] } ]
Connect to your cluster in MongoDB Compass.
Open MongoDB Compass and connect to your cluster. For detailed instructions on connecting, see Connect via Compass.
Run the Atlas Search query against the collection.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
To run this query in MongoDB Compass:
Click the Aggregations tab.
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.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
Pipeline StageQuery$search
{ "text": { "query": "Mobile", "path": "name" } } $project
{ "score": { "$meta": "searchScore", }, "_id": 0, "number_of_employees": 1, "founded_year": 1, "name": 1 } $set
{ "source": "companies" } $limit
3
$unionWith
{ "coll": "inspections", "pipeline": [ { "$search": { "text": { "query": "Mobile", "path": "business_name", } } }, { "$set": { "source": "inspections", } }, { "$project": { "score": { "$meta": "searchScore" }, "source": 1, "_id": 0, "business_name": 1, "address": 1 } }, { "$limit": 3 }, { "$sort": { "score": -1 } } ] } If you enabled Auto Preview, MongoDB Compass displays the following documents next to the
$project
pipeline stage:name: "XLR8 Mobile" number_of_employees: 21 founded_year: 2006 score: 2.0815043449401855 source: "companies" name: "Pulse Mobile" number_of_employees: null founded_year: null score: 2.0815043449401855 source: "companies" name: "T-Mobile" number_of_employees: null founded_year: null score: 2.0815043449401855 source: "companies" business_name: "T. MOBILE" address: Object source: "inspections" score: 2.900916337966919 business_name: "BOOST MOBILE" address: Object source: "inspections" score: 2.900916337966919 business_name: "SPRING MOBILE" address: Object source: "inspections" score: 2.900916337966919 This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
Pipeline StageQuery$search
{ text: { query: "mobile", path: "name", score: { boost: { value: 1.6 } } } } $project
{ "score": { "$meta": "searchScore", }, "_id": 0, "number_of_employees": 1, "founded_year": 1, "name": 1 } $addFields
{ source: "companies", source_count: "$$SEARCH_META.count.lowerBound" } $limit
3
$unionWith
{ coll: "inspections", pipeline: [ { $search: { text: { query: "mobile", path: "business_name" } } }, { $project: { score: { $meta: "searchScore" }, business_name: 1, address: 1, _id: 0 } }, { $limit: 3, }, { $set: { source: "inspections", source_count: "$$SEARCH_META.count.lowerBound" } }, { $sort: { score: -1 } } ] } $facet
{ allDocs: [], totalCount: [ { $group: { _id: "$source", firstCount: { $first: "$source_count" } } }, { $project: { totalCount: { $sum: "$firstCount" } } } ] } If you enabled Auto Preview, MongoDB Compass displays the following documents next to the
$project
pipeline stage:allDocs: Array (6) 0: Object name: "XLR8 Mobile" number_of_employees: 21 founded_year: 2006 score: 3.33040714263916 source: "companies" source_count: 52 1: Object name: "Pulse Mobile" number_of_employees: null founded_year: null score: 3.33040714263916 source: "companies" source_count: 52 2: Object name: "T-Mobile" number_of_employees: null founded_year: null score: 3.33040714263916 source: "companies" source_count: 52 3: Object business_name: "T. MOBILE" address: Object score: 2.900916337966919 source: "inspections" source_count: 456 4: Object business_name: "BOOST MOBILE" address: Object score: 2.900916337966919 source: "inspections" source_count: 456 5: Object business_name: "SPRING MOBILE" address: Object score: 2.900916337966919 source: "inspections" source_count: 456 totalCount: Array (2) 0: Object _id: "companies" totalCount: 52 1: Object _id: "inspections" totalCount: 456
Set up and initialize the .NET/C# project for the query.
Create a new directory called
search-with-unionwith
and initialize your project with the dotnet new command.mkdir search-with-unionwith cd search-with-unionwith dotnet new console Add the .NET/C# Driver to your project as a dependency.
dotnet add package MongoDB.Driver
Copy and paste the query into the Program.cs
file.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
1 using MongoDB.Bson; 2 using MongoDB.Driver; 3 using MongoDB.Driver.Search; 4 5 public class Program 6 { 7 public static void Main(string[] args) 8 { 9 // connect to your Atlas cluster 10 string connectionString = "<connection-string>"; 11 var client = new MongoClient(connectionString); 12 13 // define namespace 14 var database = client.GetDatabase("sample_training"); 15 var collection = database.GetCollection<BsonDocument>("companies"); 16 17 // define pipeline stage 18 var searchStage1 = new BsonDocument("$search", new BsonDocument{{ "text", new BsonDocument 19 {{ "query", "Mobile" },{ "path", "name" }} 20 }}); 21 var projectStage1 = new BsonDocument("$project", new BsonDocument{ 22 { "score", new BsonDocument("$meta", "searchScore") }, 23 { "_id", 0 },{ "number_of_employees", 1 },{ "founded_year", 1 },{ "name", 1 } 24 }); 25 var setStage1 = new BsonDocument("$set", new BsonDocument{{ "source", "companies" }}); 26 var limitStage1 = new BsonDocument("$limit", 3); 27 28 // define subpipeline 29 var searchStage2 = new BsonDocument("$search", new BsonDocument{{ "text", new BsonDocument 30 {{ "query", "Mobile" },{ "path", "business_name" }} 31 }}); 32 var setStage2 = new BsonDocument("$set", new BsonDocument{ { "source", "inspections" } }); 33 var projectStage2 = new BsonDocument("$project", new BsonDocument{ 34 { "score", new BsonDocument("$meta", "searchScore") }, 35 { "source", 1 }, { "_id", 0 }, { "business_name", 1 }, { "address", 1 } 36 }); 37 var limitStage2 = new BsonDocument("$limit", 3); 38 var sortStage2 = new BsonDocument("$sort", new BsonDocument{{ "score", -1 }}); 39 var unionWithPipeline = new List<BsonDocument>{searchStage2, setStage2, projectStage2, limitStage2, sortStage2}; 40 var unionWithStage = new BsonDocument("$unionWith", new BsonDocument 41 { 42 { "coll", "inspections" }, 43 { "pipeline", new BsonArray(unionWithPipeline) } 44 }); 45 var aggregationPipeline = new List<BsonDocument> {searchStage1, projectStage1, setStage1, limitStage1,unionWithStage}; 46 47 // run pipeline 48 var result = collection.Aggregate<BsonDocument>(aggregationPipeline).ToList(); 49 50 //print results 51 foreach (var document in result) 52 { 53 Console.WriteLine(document); 54 } 55 } 56 }
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
1 using MongoDB.Bson; 2 using MongoDB.Driver; 3 4 public class Program 5 { 6 public static void Main(string[] args) 7 { 8 // connect to your Atlas cluster 9 var client = new MongoClient("<connection-string>"); 10 11 // define namespace 12 var database = client.GetDatabase("sample_training"); 13 var collection = database.GetCollection<BsonDocument>("companies"); 14 15 // define pipeline 16 var pipeline = new BsonDocument[] 17 { 18 new BsonDocument("$search", new BsonDocument{ 19 { "text", new BsonDocument{ 20 { "query", "mobile" }, { "path", "name" }, 21 { "score", new BsonDocument{ 22 { "boost", new BsonDocument{ { "value", 1.6 } }} 23 }} 24 }} 25 }), 26 new BsonDocument("$project", new BsonDocument{ 27 { "score", new BsonDocument("$meta", "searchScore") }, 28 { "_id", 0 }, 29 { "number_of_employees", 1 }, { "founded_year", 1 }, { "name", 1 } 30 }), 31 new BsonDocument("$addFields", new BsonDocument{ 32 { "source", "companies" }, 33 { "source_count", "$$SEARCH_META.count.lowerBound" } 34 }), 35 new BsonDocument("$limit", 3), 36 new BsonDocument("$unionWith", new BsonDocument{ 37 { "coll", "inspections" }, 38 { "pipeline", new BsonArray{ 39 new BsonDocument("$search", new BsonDocument{ 40 { "text", new BsonDocument{ 41 { "query", "mobile" }, 42 { "path", "business_name" } 43 }} 44 }), 45 new BsonDocument("$project", new BsonDocument{ 46 { "score", new BsonDocument("$meta", "searchScore") }, 47 { "business_name", 1 }, { "address", 1 }, { "_id", 0 } 48 }), 49 new BsonDocument("$limit", 3), 50 new BsonDocument("$set", new BsonDocument{ 51 { "source", "inspections" }, 52 { "source_count", "$$SEARCH_META.count.lowerBound" } 53 }), 54 new BsonDocument("$sort", new BsonDocument{ 55 { "score", -1 } 56 }) 57 }} 58 }), 59 new BsonDocument("$facet", new BsonDocument{ 60 { "allDocs", new BsonArray() }, 61 { "totalCount", new BsonArray{ 62 new BsonDocument("$group", new BsonDocument{ 63 { "_id", "$source" }, 64 { "firstCount", new BsonDocument("$first", "$source_count") } 65 }), 66 new BsonDocument("$project", new BsonDocument{ 67 { "totalCount", new BsonDocument("$sum", "$firstCount") } 68 }) 69 }} 70 }) 71 }; 72 73 // run pipeline 74 var result = collection.Aggregate<BsonDocument>(pipeline).ToList(); 75 76 //print results 77 foreach (var document in result) 78 { 79 Console.WriteLine(document); 80 } 81 } 82 }
Replace the <connection-string>
in the query and then save the file.
Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.
Compile and run the Program.cs
file.
dotnet run search-with-unionwith.csproj
{ "name" : "XLR8 Mobile", "number_of_employees" : 21, "founded_year" : 2006, "score" : 2.0815043449401855, "source" : "companies" } { "name" : "Pulse Mobile", "number_of_employees" : null, "founded_year" : null, "score" : 2.0815043449401855, "source" : "companies" } { "name" : "T-Mobile", "number_of_employees" : null, "founded_year" : null, "score" : 2.0815043449401855, "source" : "companies" } { "business_name" : "T. MOBILE", "address" : { "city" : "BROOKLYN", "zip" : 11209, "street" : "86TH ST", "number" : 440 }, "source" : "inspections", "score" : 2.9009163379669189 } { "business_name" : "BOOST MOBILE", "address" : { "city" : "BRONX", "zip" : 10458, "street" : "E FORDHAM RD", "number" : 261 }, "source" : "inspections", "score" : 2.9009163379669189 } { "business_name" : "SPRING MOBILE", "address" : { "city" : "SOUTH RICHMOND HILL", "zip" : 11419, "street" : "LIBERTY AVE", "number" : 12207 }, "source" : "inspections", "score" : 2.9009163379669189 }
dotnet run search-with-unionwith.csproj
{ "allDocs" : [ { "name" : "XLR8 Mobile", "number_of_employees" : 21, "founded_year" : 2006, "score" : 3.3304071426391602, "source" : "companies", "source_count" : NumberLong(52) }, { "name" : "Pulse Mobile", "number_of_employees" : null, "founded_year" : null, "score" : 3.3304071426391602, "source" : "companies", "source_count" : NumberLong(52) }, { "name" : "T-Mobile", "number_of_employees" : null, "founded_year" : null, "score" : 3.3304071426391602, "source" : "companies", "source_count" : NumberLong(52) }, { "business_name" : "T. MOBILE", "address" : { "city" : "BROOKLYN", "zip" : 11209, "street" : "86TH ST", "number" : 440 }, "score" : 2.9009163379669189, "source" : "inspections", "source_count" : NumberLong(456) }, { "business_name" : "BOOST MOBILE", "address" : { "city" : "BRONX", "zip" : 10458, "street" : "E FORDHAM RD", "number" : 261 }, "score" : 2.9009163379669189, "source" : "inspections", "source_count" : NumberLong(456) }, { "business_name" : "SPRING MOBILE", "address" : { "city" : "SOUTH RICHMOND HILL", "zip" : 11419, "street" : "LIBERTY AVE", "number" : 12207 }, "score" : 2.9009163379669189, "source" : "inspections", "source_count" : NumberLong(456) } ], "totalCount" : [ { "_id" : "companies", "totalCount" : NumberLong(52) }, { "_id" : "inspections", "totalCount" : NumberLong(456) } ] }
Copy and paste the query into the search-with-unionwith-query.go
file.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
1 package main 2 import ( 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 12 func 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 22 // set namespace 23 collection := client.Database("sample_training").Collection("companies") 24 // define pipeline 25 searchStage := bson.D{{"$search", bson.D{ 26 {"text", bson.D{ 27 {"query", "Mobile"}, {"path", "name"}, 28 }}, 29 }}} 30 projectStage := bson.D{{"$project", bson.D{ 31 {"score", bson.D{{"$meta", "searchScore"}}}, 32 {"_id", 0}, 33 {"number_of_employees", 1}, 34 {"founded_year", 1}, 35 {"name", 1}, 36 }}} 37 setStage := bson.D{{"$set", bson.D{{"source", "companies"}}}} 38 limitStage := bson.D{{"$limit", 5}} 39 uinionWithStage := bson.D{{"$unionWith", bson.D{ 40 {"coll", "inspections"}, 41 {"pipeline", bson.A{ 42 bson.D{{"$search", bson.D{ 43 {"text", bson.D{ 44 {"query", "Mobile"}, {"path", "business_name"}, 45 }}, 46 }}}, 47 bson.D{{"$set", bson.D{{"source", "inspections"}}}}, 48 bson.D{{"$project", bson.D{ 49 {"score", bson.D{{"$meta", "searchScore"}}}, 50 {"source", 1}, 51 {"_id", 0}, 52 {"business_name", 1}, 53 {"address", 1}, 54 }}}, 55 bson.D{{"$limit", 3}}, 56 bson.D{{"$sort", bson.D{{"score", -1}}}}, 57 }}, 58 }}} 59 // specify the amount of time the operation can run on the server 60 opts := options.Aggregate().SetMaxTime(5 * time.Second) 61 // run pipeline 62 cursor, err := collection.Aggregate(ctx, mongo.Pipeline{searchStage, projectStage, setStage, limitStage, uinionWithStage}, opts) 63 if err != nil { 64 panic(err) 65 } 66 // print results 67 var results []bson.D 68 if err = cursor.All(context.TODO(), &results); err != nil { 69 panic(err) 70 } 71 for _, result := range results { 72 fmt.Println(result) 73 } 74 }
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
1 package main 2 import ( 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 12 func 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_training").Collection("companies") 23 // define pipeline 24 searchStage := bson.D{{"$search", bson.D{ 25 {"text", bson.D{ 26 {"query", "Mobile"}, {"path", "name"}, {"score", bson.D{{"boost", bson.D{{"value", 1.6}}}}}, 27 }}, 28 }}} 29 projectStage := bson.D{{"$project", bson.D{ 30 {"score", bson.D{{"$meta", "searchScore"}}}, 31 {"_id", 0}, 32 {"number_of_employees", 1}, 33 {"founded_year", 1}, 34 {"name", 1}, 35 }}} 36 addFieldsStage := bson.D{{"$set", bson.D{ 37 {"source", "companies"}, 38 {"source_count", "$$SEARCH_META.count.lowerBound"}, 39 }}} 40 limitStage := bson.D{{"$limit", 3}} 41 uinionWithStage := bson.D{{"$unionWith", bson.D{ 42 {"coll", "inspections"}, 43 {"pipeline", bson.A{ 44 bson.D{{"$search", bson.D{ 45 {"text", bson.D{ 46 {"query", "mobile"}, {"path", "business_name"}, 47 }}, 48 }}}, 49 bson.D{{"$project", bson.D{ 50 {"score", bson.D{{"$meta", "searchScore"}}}, 51 {"business_name", 1}, 52 {"address", 1}, 53 {"_id", 0}, 54 }}}, 55 bson.D{{"$limit", 3}}, 56 bson.D{{"$set", bson.D{ 57 {"source", "inspections"}, 58 {"source_count", "$$SEARCH_META.count.lowerBound"}, 59 }}}, 60 bson.D{{"$sort", bson.D{{"score", -1}}}}, 61 }}, 62 }}} 63 facetStage := bson.D{{"$facet", bson.D{ 64 {"allDocs", bson.A{}}, 65 {"totalCount", bson.A{ 66 bson.D{ 67 {"$group", bson.D{ 68 {"_id", "$source"}, 69 {"firstCount", bson.D{{"$first", "$source_count"}}}, 70 }}, 71 }, 72 bson.D{{"$project", bson.D{{"totalCount", bson.D{{"$sum", "$firstCount"}}}}}}, 73 }}, 74 }}} 75 // specify the amount of time the operation can run on the server 76 opts := options.Aggregate().SetMaxTime(5 * time.Second) 77 // run pipeline 78 cursor, err := collection.Aggregate(ctx, mongo.Pipeline{searchStage, projectStage, addFieldsStage, limitStage, uinionWithStage, facetStage}, opts) 79 if err != nil { 80 panic(err) 81 } 82 // print results 83 var results []bson.D 84 if err = cursor.All(context.TODO(), &results); err != nil { 85 panic(err) 86 } 87 for _, result := range results { 88 fmt.Println(result) 89 } 90 }
Replace the <connection-string>
in the query and then save the file.
Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.
Run the command to query your collection.
go run search-with-unionwith-query.go
[{name XLR8 Mobile} {number_of_employees 21} {founded_year 2006} {score 3.33040714263916} {source companies} {source_count 52}] [{name Pulse Mobile} {number_of_employees <nil>} {founded_year <nil>} {score 3.33040714263916} {source companies} {source_count 52}] [{name T-Mobile} {number_of_employees <nil>} {founded_year <nil>} {score 3.33040714263916} {source companies} {source_count 52}] [{business_name T. MOBILE} {address [{city BROOKLYN} {zip 11209} {street 86TH ST} {number 440}]} {score 2.900916337966919} {source inspections} {source_count 456}] [{business_name BOOST MOBILE} {address [{city BRONX} {zip 10458} {street E FORDHAM RD} {number 261}]} {score 2.900916337966919} {source inspections} {source_count 456}] [{business_name SPRING MOBILE} {address [{city SOUTH RICHMOND HILL} {zip 11419} {street LIBERTY AVE} {number 12207}]} {score 2.900916337966919} {source inspections} {source_count 456}]
go run search-with-unionwith-query.go
[ {allDocs [ [{name XLR8 Mobile} {number_of_employees 21} {founded_year 2006} {score 3.33040714263916} {source companies} {source_count 52}] [{name Pulse Mobile} {number_of_employees <nil>} {founded_year <nil>} {score 3.33040714263916} {source companies} {source_count 52}] [{name T-Mobile} {number_of_employees <nil>} {founded_year <nil>} {score 3.33040714263916} {source companies} {source_count 52}] [{business_name T. MOBILE} {address [{city BROOKLYN} {zip 11209} {street 86TH ST} {number 440}]} {score 2.900916337966919} {source inspections} {source_count 456}] [{business_name BOOST MOBILE} {address [{city BRONX} {zip 10458} {street E FORDHAM RD} {number 261}]} {score 2.900916337966919} {source inspections} {source_count 456}] [{business_name SPRING MOBILE} {address [{city SOUTH RICHMOND HILL} {zip 11419} {street LIBERTY AVE} {number 12207}]} {score 2.900916337966919} {source inspections} {source_count 456}] ]} {totalCount [ [{_id inspections} {totalCount 456}] [{_id companies} {totalCount 52}] ]} ]
Copy and paste the query into the SearchWithUnionwithQuery.java
file.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
1 import com.mongodb.client.MongoClients; 2 import com.mongodb.client.MongoClient; 3 import com.mongodb.client.MongoDatabase; 4 import org.bson.Document; 5 import java.util.ArrayList; 6 import java.util.Arrays; 7 import java.util.List; 8 9 public class SearchWithUnionwith { 10 public static void main(String[] args) { 11 // connect to Atlas cluster 12 try (MongoClient mongoClient = MongoClients.create("<connection-string>")) { 13 // get database name 14 MongoDatabase database = mongoClient.getDatabase("sample_training"); 15 // define pipeline 16 List<Document> pipeline1 = Arrays.asList( 17 new Document("$search", new Document("text", 18 new Document("query", "Mobile") 19 .append("path", "name"))), 20 new Document("$project", new Document("score", 21 new Document("$meta", "searchScore")) 22 .append("_id", 0) 23 .append("number_of_employees", 1) 24 .append("founded_year", 1) 25 .append("name", 1)), 26 new Document("$set", new Document("source", "companies")), 27 new Document("$limit", 3) 28 ); 29 30 List<Document> pipeline2 = Arrays.asList( 31 new Document("$search", new Document("text", 32 new Document("query", "Mobile") 33 .append("path", "business_name"))), 34 new Document("$set", new Document("source", "inspections")), 35 new Document("$project", new Document("score", 36 new Document("$meta", "searchScore")) 37 .append("source", 1) 38 .append("_id", 0) 39 .append("business_name", 1) 40 .append("address", 1)), 41 new Document("$limit", 3), 42 new Document("$sort", new Document("score", -1)) 43 ); 44 45 List<Document> unionWithStage = new ArrayList<>(); 46 Document unionWith = new Document("$unionWith", new Document("coll", "inspections") 47 .append("pipeline", pipeline2)); 48 unionWithStage.add(unionWith); 49 50 List<Document> finalPipeline = new ArrayList<>(pipeline1); 51 finalPipeline.addAll(unionWithStage); 52 // run pipeline and print results 53 database.getCollection("companies").aggregate(finalPipeline) 54 .forEach(doc -> System.out.println(doc.toJson())); 55 } 56 } 57 }
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
1 import com.mongodb.client.MongoClients; 2 import com.mongodb.client.MongoCollection; 3 import com.mongodb.client.MongoClient; 4 import org.bson.Document; 5 6 public class SearchWithUnionwith { 7 public static void main(String[] args) { 8 // connect to Atlas cluster 9 try (MongoClient mongoClient = MongoClients.create("<connection-string>")) { 10 // define namespace 11 MongoCollection<Document> collection = mongoClient.getDatabase("sample_training").getCollection("companies"); 12 // define pipeline 13 Document searchStage = new Document("$search", new Document("text", 14 new Document("query", "mobile") 15 .append("path", "name") 16 .append("score", new Document("boost", new Document("value", 1.6))) 17 ) 18 ); 19 20 Document projectStage = new Document("$project", new Document("score", new Document("$meta", "searchScore")) 21 .append("_id", 0) 22 .append("number_of_employees", 1) 23 .append("founded_year", 1) 24 .append("name", 1) 25 ); 26 27 Document addFieldsStage = new Document("$addFields", new Document("source", "companies") 28 .append("source_count", "$$SEARCH_META.count.lowerBound") 29 ); 30 31 Document limitStage = new Document("$limit", 3); 32 33 Document unionWithStage = new Document("$unionWith", new Document("coll", "inspections") 34 .append("pipeline", java.util.Arrays.asList( 35 new Document("$search", new Document("text", 36 new Document("query", "mobile") 37 .append("path", "business_name") 38 )), 39 new Document("$project", new Document("score", new Document("$meta", "searchScore")) 40 .append("business_name", 1) 41 .append("address", 1) 42 .append("_id", 0) 43 ), 44 new Document("$limit", 3), 45 new Document("$set", new Document("source", "inspections") 46 .append("source_count", "$$SEARCH_META.count.lowerBound") 47 ), 48 new Document("$sort", new Document("score", -1)) 49 )) 50 ); 51 52 Document facetStage = new Document("$facet", new Document("allDocs", java.util.Arrays.asList()) 53 .append("totalCount", java.util.Arrays.asList( 54 new Document("$group", new Document("_id", "$source") 55 .append("firstCount", new Document("$first", "$source_count")) 56 ), 57 new Document("$project", new Document("totalCount", 58 new Document("$sum", "$firstCount") 59 )) 60 )) 61 ); 62 // run pipeline and print results 63 collection.aggregate(java.util.Arrays.asList( 64 searchStage, projectStage, addFieldsStage, limitStage, unionWithStage, facetStage 65 )).forEach(doc -> System.out.println(doc.toJson())); 66 } 67 } 68 }
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;
Replace the <connection-string>
in the query and then save the file.
Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.
Compile and run the UinionwithWithSearchQuery.java
file.
javac SearchWithUnionwithQuery.java java SearchWithUnionwithQuery
{"name": "XLR8 Mobile", "number_of_employees": 21, "founded_year": 2006, "score": 2.0815043449401855, "source": "companies"} {"name": "Pulse Mobile", "number_of_employees": null, "founded_year": null, "score": 2.0815043449401855, "source": "companies"} {"name": "T-Mobile", "number_of_employees": null, "founded_year": null, "score": 2.0815043449401855, "source": "companies"} {"business_name": "T. MOBILE", "address": {"city": "BROOKLYN", "zip": 11209, "street": "86TH ST", "number": 440}, "source": "inspections", "score": 2.900916337966919} {"business_name": "BOOST MOBILE", "address": {"city": "BRONX", "zip": 10458, "street": "E FORDHAM RD", "number": 261}, "source": "inspections", "score": 2.900916337966919} {"business_name": "SPRING MOBILE", "address": {"city": "SOUTH RICHMOND HILL", "zip": 11419, "street": "LIBERTY AVE", "number": 12207}, "source": "inspections", "score": 2.900916337966919}
javac SearchWithUnionwithQuery.java java SearchWithUnionwithQuery
{ "allDocs": [ {"name": "XLR8 Mobile", "number_of_employees": 21, "founded_year": 2006, "score": 3.33040714263916, "source": "companies", "source_count": 52}, {"name": "Pulse Mobile", "number_of_employees": null, "founded_year": null, "score": 3.33040714263916, "source": "companies", "source_count": 52}, {"name": "T-Mobile", "number_of_employees": null, "founded_year": null, "score": 3.33040714263916, "source": "companies", "source_count": 52}, {"business_name": "T. MOBILE", "address": {"city": "BROOKLYN", "zip": 11209, "street": "86TH ST", "number": 440}, "score": 2.900916337966919, "source": "inspections", "source_count": 456}, {"business_name": "BOOST MOBILE", "address": {"city": "BRONX", "zip": 10458, "street": "E FORDHAM RD", "number": 261}, "score": 2.900916337966919, "source": "inspections", "source_count": 456}, {"business_name": "SPRING MOBILE", "address": {"city": "SOUTH RICHMOND HILL", "zip": 11419, "street": "LIBERTY AVE", "number": 12207}, "score": 2.900916337966919, "source": "inspections", "source_count": 456} ], "totalCount": [ {"_id": "companies", "totalCount": 52}, {"_id": "inspections", "totalCount": 456} ] }
Copy and paste the query into the SearchWithUnionwithQuery.kt
file.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
1 import com.mongodb.kotlin.client.coroutine.MongoClient 2 import kotlinx.coroutines.runBlocking 3 import org.bson.Document 4 5 fun main() { 6 // connect to Atlas cluster 7 val uri = "<connection-string>" 8 val mongoClient = MongoClient.create(uri) 9 10 // set namespace 11 val database = mongoClient.getDatabase("sample_training") 12 val collection = database.getCollection<Document>("companies") 13 14 runBlocking { 15 // define pipeline 16 val pipeline1 = listOf( 17 Document("\$search", Document("text", 18 Document("query", "Mobile") 19 .append("path", "name"))), Document("\$project", Document("score", 20 Document("\$meta", "searchScore")) 21 .append("_id", 0) 22 .append("number_of_employees", 1) 23 .append("founded_year", 1) 24 .append("name", 1)), Document("\$set", Document("source", "companies")), 25 Document("\$limit", 3) 26 ) 27 28 val pipeline2 = listOf( 29 Document( 30 "\$search", Document( 31 "text", 32 Document("query", "Mobile") 33 .append("path", "business_name") 34 ) 35 ), 36 Document("\$set", Document("source", "inspections")), 37 Document( 38 "\$project", Document( 39 "score", 40 Document("\$meta", "searchScore") 41 ) 42 .append("source", 1) 43 .append("_id", 0) 44 .append("business_name", 1) 45 .append("address", 1) 46 ), 47 Document("\$limit", 3), 48 Document("\$sort", Document("score", -1)) 49 ) 50 51 val unionWithStage: MutableList<Document> = ArrayList() 52 val unionWith = Document( 53 "\$unionWith", Document("coll", "inspections") 54 .append("pipeline", pipeline2) 55 ) 56 unionWithStage.add(unionWith) 57 val finalPipeline: MutableList<Document> = ArrayList(pipeline1) 58 finalPipeline.addAll(unionWithStage) 59 60 // run pipeline and print results 61 val resultsFlow = collection.aggregate<Document>(finalPipeline) 62 resultsFlow.collect { println(it) } 63 64 } 65 mongoClient.close() 66 }
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
1 import com.mongodb.kotlin.client.coroutine.MongoClient 2 import kotlinx.coroutines.runBlocking 3 import org.bson.Document 4 import java.util.* 5 6 fun main() { 7 // connect to Atlas cluster 8 val uri = "<connection-string>" 9 val mongoClient = MongoClient.create(uri) 10 11 // set namespace 12 val database = mongoClient.getDatabase("sample_training") 13 val collection = database.getCollection<Document>("companies") 14 15 runBlocking { 16 // define pipeline stages 17 val searchStage = Document( 18 "\$search", Document( 19 "text", 20 Document("query", "mobile") 21 .append("path", "name") 22 .append("score", Document("boost", Document("value", 1.6))) 23 ) 24 ) 25 26 val projectStage = Document( 27 "\$project", Document("score", Document("\$meta", "searchScore")) 28 .append("_id", 0) 29 .append("number_of_employees", 1) 30 .append("founded_year", 1) 31 .append("name", 1) 32 ) 33 34 val addFieldsStage = Document( 35 "\$addFields", Document("source", "companies") 36 .append("source_count", "$\$SEARCH_META.count.lowerBound") 37 ) 38 39 val limitStage = Document("\$limit", 3) 40 41 val unionWithStage = Document( 42 "\$unionWith", Document("coll", "inspections") 43 .append( 44 "pipeline", Arrays.asList( 45 Document( 46 "\$search", Document( 47 "text", 48 Document("query", "mobile") 49 .append("path", "business_name") 50 ) 51 ), 52 Document( 53 "\$project", Document("score", Document("\$meta", "searchScore")) 54 .append("business_name", 1) 55 .append("address", 1) 56 .append("_id", 0) 57 ), 58 Document("\$limit", 3), 59 Document( 60 "\$set", Document("source", "inspections") 61 .append("source_count", "$\$SEARCH_META.count.lowerBound") 62 ), 63 Document("\$sort", Document("score", -1)) 64 ) 65 ) 66 ) 67 68 val facetStage = Document( 69 "\$facet", Document("allDocs", Arrays.asList<Any>()) 70 .append( 71 "totalCount", Arrays.asList( 72 Document( 73 "\$group", Document("_id", "\$source") 74 .append("firstCount", Document("\$first", "\$source_count")) 75 ), 76 Document( 77 "\$project", Document( 78 "totalCount", 79 Document("\$sum", "\$firstCount") 80 ) 81 ) 82 ) 83 ) 84 ) 85 86 // run pipeline and print results 87 val resultsFlow = collection.aggregate<Document>( 88 listOf( 89 searchStage, 90 projectStage, 91 addFieldsStage, 92 limitStage, 93 unionWithStage, 94 facetStage 95 ) 96 ) 97 resultsFlow.collect { println(it) } 98 99 } 100 mongoClient.close() 101 }
Replace the <connection-string>
in the query and then save the file.
Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.
Run the SearchWithUnionwithQuery.kt
file.
When you run the SearchWithUnionwithQuery.kt
program in your IDE, it prints
the following documents:
Document{{name=XLR8 Mobile, number_of_employees=21, founded_year=2006, score=2.0815043449401855, source=companies}} Document{{name=Pulse Mobile, number_of_employees=null, founded_year=null, score=2.0815043449401855, source=companies}} Document{{name=Mobile Trend, number_of_employees=null, founded_year=2003, score=2.0815043449401855, source=companies}} Document{{business_name=T-MOBILE, address=Document{{city=BROOKLYN, zip=11229, street=AVENUE U, number=1616}}, source=inspections, score=2.900916337966919}} Document{{business_name=BOOST MOBILE, address=Document{{city=BRONX, zip=10458, street=E FORDHAM RD, number=261}}, source=inspections, score=2.900916337966919}} Document{{business_name=SPRING MOBILE, address=Document{{city=SOUTH RICHMOND HILL, zip=11419, street=LIBERTY AVE, number=12207}}, source=inspections, score=2.900916337966919}}
When you run the SearchWithUnionwithQuery.kt
program in your IDE, it prints
the following result:
Document{{allDocs=[Document{{name=XLR8 Mobile, number_of_employees=21, founded_year=2006, score=3.33040714263916, source=companies, source_count=52}}, Document{{name=Pulse Mobile, number_of_employees=null, founded_year=null, score=3.33040714263916, source=companies, source_count=52}}, Document{{name=Mobile Trend, number_of_employees=null, founded_year=2003, score=3.33040714263916, source=companies, source_count=52}}, Document{{business_name=T-MOBILE, address=Document{{city=BROOKLYN, zip=11229, street=AVENUE U, number=1616}}, score=2.900916337966919, source=inspections, source_count=456}}, Document{{business_name=BOOST MOBILE, address=Document{{city=BRONX, zip=10458, street=E FORDHAM RD, number=261}}, score=2.900916337966919, source=inspections, source_count=456}}, Document{{business_name=SPRING MOBILE, address=Document{{city=SOUTH RICHMOND HILL, zip=11419, street=LIBERTY AVE, number=12207}}, score=2.900916337966919, source=inspections, source_count=456}}], totalCount=[Document{{_id=inspections, totalCount=456}}, Document{{_id=companies, totalCount=52}}]}}
Copy and paste the sample query into the search-with-unionwith-query.js
file.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
1 const MongoClient = require("mongodb").MongoClient; 2 const assert = require("assert"); 3 4 const agg = [ 5 { 6 '$search': { 7 'text': { 'query': 'Mobile', 'path': 'name' } 8 } 9 }, { 10 '$project': { 11 'score': { '$meta': 'searchScore' }, 12 '_id': 0, 'number_of_employees': 1, 'founded_year': 1, 'name': 1 13 } 14 }, { 15 '$set': { 'source': 'companies' } 16 }, { 17 '$limit': 3 18 }, { 19 '$unionWith': { 20 'coll': 'inspections', 21 'pipeline': [ 22 { 23 '$search': { 24 'text': { 'query': 'Mobile', 'path': 'business_name' } 25 } 26 }, { 27 '$set': { 'source': 'inspections' } 28 }, { 29 '$project': { 30 'score': { '$meta': 'searchScore' }, 31 'source': 1, '_id': 0, 'business_name': 1, 'address': 1 32 } 33 }, { 34 '$limit': 3 35 }, { 36 '$sort': { 'score': -1 } 37 } 38 ] 39 } 40 } 41 ]; 42 43 MongoClient.connect( 44 "<connection-string>", 45 { useNewUrlParser: true, useUnifiedTopology: true }, 46 async function (connectErr, client) { 47 assert.equal(null, connectErr); 48 const coll = client.db("sample_training").collection("companies"); 49 let cursor = await coll.aggregate(agg); 50 await cursor.forEach((doc) => console.log(doc)); 51 client.close(); 52 } 53 );
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
1 const MongoClient = require("mongodb").MongoClient; 2 const assert = require("assert"); 3 4 const agg = [ 5 {'$search': { 'text': { 6 'query': 'mobile', 7 'path': 'name', 8 'score': { 9 'boost': { 'value': 1.6 } 10 } 11 }}}, 12 {'$project': { 13 'score': { '$meta': 'searchScore' }, 14 '_id': 0, 15 'number_of_employees': 1, 16 'founded_year': 1, 17 'name': 1 18 }}, 19 {'$addFields': { 20 'source': 'companies', 21 'source_count': '$$SEARCH_META.count.lowerBound' 22 }}, 23 {'$limit': 3}, 24 {'$unionWith': { 25 'coll': 'inspections', 26 'pipeline': [ 27 {'$search': { 28 'text': { 'query': 'mobile', 'path': 'business_name' } 29 }}, 30 {'$project': { 31 'score': { '$meta': 'searchScore' }, 32 'business_name': 1, 33 'address': 1, 34 '_id': 0 35 }}, 36 {'$limit': 3}, 37 {'$set': { 38 'source': 'inspections', 39 'source_count': '$$SEARCH_META.count.lowerBound' 40 }}, 41 {'$sort': { 'score': -1 } } 42 ] 43 }}, 44 {'$facet': { 45 'allDocs': [], 46 'totalCount': [ 47 {'$group': { 48 '_id': '$source', 49 'firstCount': { '$first': '$source_count' } 50 }}, 51 {'$project': { 52 'totalCount': { '$sum': '$firstCount' } 53 }} 54 ] 55 }} 56 ]; 57 58 MongoClient.connect( 59 "<connection-string>", 60 { useNewUrlParser: true, useUnifiedTopology: true }, 61 async function (connectErr, client) { 62 assert.equal(null, connectErr); 63 const coll = client.db("sample_training").collection("companies"); 64 let cursor = await coll.aggregate(agg); 65 await cursor.forEach((doc) => console.log(doc)); 66 client.close(); 67 } 68 );
Replace the <connection-string>
in the query and then save the file.
Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.
Query your collection.
Run the following command to query your collection:
node unionwith-with-search-query.js
{ name: 'SoftBank Mobile', number_of_employees: null, founded_year: null, score: 2.0815043449401855, source: 'companies' } { name: 'Mobile Factory', number_of_employees: 53, founded_year: 2001, score: 2.0815043449401855, source: 'companies' } { name: 'ZOOZ Mobile', number_of_employees: 5, founded_year: 2008, score: 2.0815043449401855, source: 'companies' } { business_name: 'T. MOBILE', address: { city: 'BROOKLYN', zip: 11209, street: '86TH ST', number: 440 }, source: 'inspections', score: 2.900916337966919 } { business_name: 'BOOST MOBILE', address: { city: 'BRONX', zip: 10458, street: 'E FORDHAM RD', number: 261 }, source: 'inspections', score: 2.900916337966919 } { business_name: 'T-MOBILE', address: { city: 'BROOKLYN', zip: 11229, street: 'AVENUE U', number: 1616 }, source: 'inspections', score: 2.900916337966919 }
node unionwith-with-search-query.js
{ allDocs: [ { name: 'XLR8 Mobile', number_of_employees: 21, founded_year: 2006, score: 3.33040714263916, source: 'companies', source_count: 52 }, { name: 'Pulse Mobile', number_of_employees: null, founded_year: null, score: 3.33040714263916, source: 'companies', source_count: 52 }, { name: 'T-Mobile', number_of_employees: null, founded_year: null, score: 3.33040714263916, source: 'companies', source_count: 52 }, { business_name: 'T. MOBILE', address: [Object], score: 2.900916337966919, source: 'inspections', source_count: 456 }, { business_name: 'BOOST MOBILE', address: [Object], score: 2.900916337966919, source: 'inspections', source_count: 456 }, { business_name: 'SPRING MOBILE', address: [Object], score: 2.900916337966919, source: 'inspections', source_count: 456 } ], totalCount: [ { _id: 'companies', totalCount: 52 }, { _id: 'inspections', totalCount: 456 } ] }
Copy and paste the query into the search-with-unionwith-query.py
file.
The following query searches both the companies
and
inspections
collections for the term mobile
in the name
and business_name
fields respectively.
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$set
stage to add a new field namedsource
that identifies the collection of the output documents.
1 import pymongo 2 import dns 3 4 client = pymongo.MongoClient('<connection-string>') 5 result = client['sample_training']['companies'].aggregate([ 6 { 7 '$search': { 8 'text': { 'query': 'Mobile', 'path': 'name' } 9 } 10 }, { 11 '$project': { 12 'score': { '$meta': 'searchScore' }, '_id': 0, 'number_of_employees': 1, 'founded_year': 1, 'name': 1 13 } 14 }, { 15 '$set': { 'source': 'companies' } 16 }, { 17 '$limit': 3 18 }, { 19 '$unionWith': { 20 'coll': 'inspections', 21 'pipeline': [ 22 { 23 '$search': { 24 'text': { 'query': 'Mobile', 'path': 'business_name' } 25 } 26 }, { 27 '$set': { 'source': 'inspections' } 28 }, { 29 '$project': { 30 'score': { '$meta': 'searchScore' }, 'source': 1, '_id': 0, 'business_name': 1, 'address': 1 31 } 32 }, { 33 '$limit': 3 34 }, { 35 '$sort': { 'score': -1 } 36 } 37 ] 38 } 39 } 40 ]) 41 42 for i in result: 43 print(i)
This query uses the following stages:
$search
to search for companies that includemobile
in the name.$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$addFields
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A field name
source_count
that shows a count of the output documents.
$unionWith
to do the following:Use
$search
stage in the sub-pipeline to search for inspections of companies that includemobile
in the name.Perform a union of documents from the
companies
and documents from theinspections
collections.
$project
stage to:Include only the specified fields in the results.
Add a field named
score
.
$limit
stage to limit the output to3
results from each collection.$set
stage to add the following new fields:A new field named
source
that identifies the collection of the output documents.A new field named
source_count
that shows a count of the output documents.
1 import pymongo 2 import dns 3 4 client = pymongo.MongoClient('<connection-string>') 5 result = client['sample_training']['companies'].aggregate([ 6 {'$search': { 'text': { 7 'query': 'mobile', 8 'path': 'name', 9 'score': { 'boost': { 'value': 1.6 } } 10 }}}, 11 {'$project': { 12 'score': { '$meta': 'searchScore' }, 13 '_id': 0, 14 'number_of_employees': 1, 15 'founded_year': 1, 16 'name': 1 17 }}, 18 {'$addFields': { 19 'source': 'companies', 20 'source_count': '$$SEARCH_META.count.lowerBound' 21 }}, 22 {'$limit': 3}, 23 {'$unionWith': { 24 'coll': 'inspections', 25 'pipeline': [ 26 {'$search': { 'text': { 27 'query': 'mobile', 28 'path': 'business_name' 29 }} }, 30 {'$project': { 31 'score': { '$meta': 'searchScore' }, 32 'business_name': 1, 33 'address': 1, 34 '_id': 0 35 }}, 36 {'$limit': 3}, 37 {'$set': { 38 'source': 'inspections', 39 'source_count': '$$SEARCH_META.count.lowerBound' 40 }}, 41 {'$sort': { 'score': -1 }} 42 ] 43 }}, 44 {'$facet': { 45 'allDocs': [], 46 'totalCount': [ 47 {'$group': { 48 '_id': '$source', 49 'firstCount': { '$first': '$source_count' } 50 }}, 51 {'$project': { 52 'totalCount': { '$sum': '$firstCount' } 53 }} 54 ] 55 }} 56 ]) 57 58 for i in result: 59 print(i)
Replace the <connection-string>
in the query and then save the file.
Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.
Run the command to query your collection.
python search-with-unionwith-query.py
{'name': 'XLR8 Mobile', 'number_of_employees': 21, 'founded_year': 2006, 'score': 2.0815043449401855, 'source': 'companies'} {'name': 'Pulse Mobile', 'number_of_employees': None, 'founded_year': None, 'score': 2.0815043449401855, 'source': 'companies'} {'name': 'T-Mobile', 'number_of_employees': None, 'founded_year': None, 'score': 2.0815043449401855, 'source': 'companies'} {'business_name': 'T. MOBILE', 'address': {'city': 'BROOKLYN', 'zip': 11209, 'street': '86TH ST', 'number': 440}, 'source': 'inspections', 'score': 2.900916337966919} {'business_name': 'BOOST MOBILE', 'address': {'city': 'BRONX', 'zip': 10458, 'street': 'E FORDHAM RD', 'number': 261}, 'source': 'inspections', 'score': 2.900916337966919} {'business_name': 'SPRING MOBILE', 'address': {'city': 'SOUTH RICHMOND HILL', 'zip': 11419, 'street': 'LIBERTY AVE', 'number': 12207}, 'source': 'inspections', 'score': 2.900916337966919}
python search-with-unionwith-query.py
{ 'allDocs': [ {'name': 'XLR8 Mobile', 'number_of_employees': 21, 'founded_year': 2006, 'score': 3.33040714263916, 'source': 'companies', 'source_count': 52}, {'name': 'Pulse Mobile', 'number_of_employees': None, 'founded_year': None, 'score': 3.33040714263916, 'source': 'companies', 'source_count': 52}, {'name': 'T-Mobile', 'number_of_employees': None, 'founded_year': None, 'score': 3.33040714263916, 'source': 'companies', 'source_count': 52}, {'business_name': 'T. MOBILE', 'address': {'city': 'BROOKLYN', 'zip': 11209, 'street': '86TH ST', 'number': 440}, 'score': 2.900916337966919, 'source': 'inspections', 'source_count': 456}, {'business_name': 'BOOST MOBILE', 'address': {'city': 'BRONX', 'zip': 10458, 'street': 'E FORDHAM RD', 'number': 261}, 'score': 2.900916337966919, 'source': 'inspections', 'source_count': 456}, {'business_name': 'SPRING MOBILE', 'address': {'city': 'SOUTH RICHMOND HILL', 'zip': 11419, 'street': 'LIBERTY AVE', 'number': 12207}, 'score': 2.900916337966919, 'source': 'inspections', 'source_count': 456} ], 'totalCount': [ {'_id': 'companies', 'totalCount': 52}, {'_id': 'inspections', 'totalCount': 456} ] }