Docs Menu
Docs Home
/
Atlas
/ /

How to Run Atlas Search Queries Against Fields in Embedded Documents

This tutorial demonstrates how to index and run Atlas Search queries against fields that are inside an array of documents, even when the array of documents is nested itself. To enable queries against these fields, you index the document fields as the embeddedDocuments type.

The tutorial on this page demonstrates queries against fields in the following types of arrays:

  • Array of documents.

  • Array of documents inside a document.

  • Array of documents inside an array of documents.

This tutorial demonstrates sample Atlas Search queries against fields in embedded documents. To learn more about these queries, see About this Tutorial.

You can complete this tutorial by using either of the following methods:

  • Use the pre-configured Atlas Search Playground.

  • Load, configure, and run it in your own cluster.

Select the tab that corresponds to your preferred method:

On the Atlas Search Playground, we have set up an embedded documents collection, pre-configured an index for the fields in the collection, and defined a query that you can run against the collection. You can also modify the collection, index, and query in the Atlas Search Playground.

To run the sample queries in the Atlas Search Playground, complete the following steps:

1

Access the nested array query example in the Atlas Search Playground.

2
3
1

Access the nested array with an object example query in the Atlas Search Playground.

2
3
1

Access the nested array within an array example query in the Atlas Search Playground.

2
3

To demonstrate how to run queries against embedded documents, this tutorial walks you through the following steps:

  1. Create a sample collection named schools with embedded documents in your Atlas cluster.

  2. Set up an Atlas Search index with embeddedDocuments fields configured at the following paths:

    • teachers field

    • teachers.classes field

    • clubs.sports field

  3. Run $search queries that search the embedded documents in the schools collection using the compound operator with the embeddedDocument and text operators.

  4. Run a $searchMeta query against an embedded document field to get a count.

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

You must begin by creating a collection named schools in an existing or new database on your Atlas cluster. After creating the collection, you must upload the sample data into your collection. To learn more about the documents in the sample collection, see About this Tutorial.

The steps in this section walk you through creating a new database and collection, and loading the sample data into your collection.

1

Warning

Navigation Improvements In Progress

We're currently rolling out a new and improved navigation experience. If the following steps don't match your view in the Atlas UI, see the preview documentation.

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

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

  3. If it's not already displayed, click Clusters in the sidebar.

    The Clusters page displays.

2

Click the Browse Collections button for your cluster.

The Data Explorer displays.

3
  1. Click Create Database to create a new database.

  2. Enter the database name and collection name.

    • In the Database Name field, specify local_school_district.

    • For the Collection Name field, specify schools.

4
  1. Select the schools collection if it's not selected.

  2. Click Insert Document for each of the sample documents to add to the collection.

  3. Click the JSON view ({}) to replace the default document.

  4. Copy and paste the following sample documents, one at a time, and click Insert to add the documents, one at a time, to the collection.

    {
    "_id": 0,
    "name": "Springfield High",
    "mascot": "Pumas",
    "teachers": [{
    "first": "Jane",
    "last": "Smith",
    "classes": [{
    "subject": "art of science",
    "grade": "12th"
    },
    {
    "subject": "applied science and practical science",
    "grade": "9th"
    },
    {
    "subject": "remedial math",
    "grade": "12th"
    },
    {
    "subject": "science",
    "grade": "10th"
    }]
    },
    {
    "first": "Bob",
    "last": "Green",
    "classes": [{
    "subject": "science of art",
    "grade": "11th"
    },
    {
    "subject": "art art art",
    "grade": "10th"
    }]
    }],
    "clubs": {
    "stem": [
    {
    "club_name": "chess",
    "description": "provides students opportunity to play the board game of chess informally and competitively in tournaments."
    },
    {
    "club_name": "kaboom chemistry",
    "description": "provides students opportunity to experiment with chemistry that fizzes and explodes."
    }
    ],
    "arts": [
    {
    "club_name": "anime",
    "description": "provides students an opportunity to discuss, show, and collaborate on anime and broaden their Japanese cultural understanding."
    },
    {
    "club_name": "visual arts",
    "description": "provides students an opportunity to train, experiment, and prepare for internships and jobs as photographers, illustrators, graphic designers, and more."
    }
    ]
    }
    }
    {
    "_id": 1,
    "name": "Evergreen High",
    "mascot": "Jaguars",
    "teachers": [{
    "first": "Jane",
    "last": "Earwhacker",
    "classes": [{
    "subject": "art",
    "grade": "9th"
    },
    {
    "subject": "science",
    "grade": "12th"
    }]
    },
    {
    "first": "John",
    "last": "Smith",
    "classes": [{
    "subject": "math",
    "grade": "12th"
    },
    {
    "subject": "art",
    "grade": "10th"
    }]
    }],
    "clubs": {
    "sports": [
    {
    "club_name": "archery",
    "description": "provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment."
    },
    {
    "club_name": "ultimate frisbee",
    "description": "provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes."
    }
    ],
    "stem": [
    {
    "club_name": "zapped",
    "description": "provides students an opportunity to make exciting gadgets and explore electricity."
    },
    {
    "club_name": "loose in the chem lab",
    "description": "provides students an opportunity to put the scientific method to the test and get elbow deep in chemistry."
    }
    ]
    }
    }
    {
    "_id": 2,
    "name": "Lincoln High",
    "mascot": "Sharks",
    "teachers": [{
    "first": "Jane",
    "last": "Smith",
    "classes": [{
    "subject": "science",
    "grade": "9th"
    },
    {
    "subject": "math",
    "grade": "12th"
    }]
    },
    {
    "first": "John",
    "last": "Redman",
    "classes": [{
    "subject": "art",
    "grade": "12th"
    }]
    }],
    "clubs": {
    "arts": [
    {
    "club_name": "ceramics",
    "description": "provides students an opportunity to acquire knowledge of form, volume, and space relationships by constructing hand-built and wheel-thrown forms of clay."
    },
    {
    "club_name": "digital art",
    "description": "provides students an opportunity to learn about design for entertainment, 3D animation, technical art, or 3D modeling."
    }
    ],
    "sports": [
    {
    "club_name": "dodgeball",
    "description": "provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves."
    },
    {
    "club_name": "martial arts",
    "description": "provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons."
    }
    ]
    }
    }

In this section, you will create an Atlas Search index for the fields in the embedded documents in the local_school_district.schools collection.

1

Warning

Navigation Improvements In Progress

We're currently rolling out a new and improved navigation experience. If the following steps don't match your view in the Atlas UI, see the preview documentation.

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

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

  3. If it's not already displayed, click Clusters in the sidebar.

    The Clusters page displays.

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.

    If you have no clusters, click Create cluster to create one. To learn more, see Create a Cluster.

  2. If your project has multiple clusters, select the cluster you want to use from the Select cluster dropdown, then click Go to Atlas Search.

    The Atlas Search page displays.

  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.

    The Atlas Search page displays.

  1. Click the cluster's name.

  2. Click the Atlas Search tab.

    The Atlas Search page displays.

3
4

Make the following selections on the page and then click Next.

Search Type

Select the Atlas Search index type.

Index Name and Data Source

Specify the following information:

  • Index Name: embedded-documents-tutorial

  • Database and Collection:

    • local_school_district database

    • schools collection

Configuration Method

For a guided experience, select Visual Editor.

To edit the raw index definition, select JSON Editor.

Note

Your Atlas Search index is named default by default. If you keep this name, then your index will be the default Search index for any Atlas Search query that does not specify a different index option in its operators. If you are creating multiple indexes, we recommend that you maintain a consistent, descriptive naming convention across your indexes.

5

To learn more about the index definition, see About this Tutorial.

  1. Click Refine Your Index.

  2. Click Add Field in the Field Mappings section and add the following fields in the Customized Configuration tab by clicking Add after configuring the settings for each field, one at a time, in the Add Field Mapping window.

    Field Name
    Data Type
    Enable Dynamic Mapping

    teachers

    EmbeddedDocuments

    On

    teachers.classes

    EmbeddedDocuments

    On

    teachers

    Document

    On

    teachers.classes

    Document

    On

    teachers.classes.grade

    StringFacet

    N/A

    clubs.sports

    EmbeddedDocuments

    On

  3. Click Add Field Mappings to open the Add Field Mapping window.

  4. Select the following from the dropdown.

  5. Click Add Field Mappings to open the Add Field Mapping window.

  6. Select the following from the dropdown.

  7. Toggle to enable Enable Dynamic Mapping if it isn't already enabled and click Add

  8. Click Save.

  9. Click Save Changes.

  1. Replace the default index definition with the following index definition.

    1{
    2 "mappings": {
    3 "dynamic": true,
    4 "fields": {
    5 "clubs": {
    6 "dynamic": true,
    7 "fields": {
    8 "sports": {
    9 "dynamic": true,
    10 "type": "embeddedDocuments"
    11 }
    12 },
    13 "type": "document"
    14 },
    15 "teachers": [
    16 {
    17 "dynamic": true,
    18 "fields": {
    19 "classes": {
    20 "dynamic": true,
    21 "type": "embeddedDocuments"
    22 }
    23 },
    24 "type": "embeddedDocuments"
    25 },
    26 {
    27 "dynamic": true,
    28 "fields": {
    29 "classes": {
    30 "dynamic": true,
    31 "fields": {
    32 "grade": {
    33 "type": "stringFacet"
    34 }
    35 },
    36 "type": "document"
    37 }
    38 },
    39 "type": "document"
    40 }
    41 ]
    42 }
    43 }
    44}
  2. Click Next.

6

Atlas displays a Toast (brief, non-interactive notification) to let you know your index is building.

7

The newly created index appears on the Atlas Search tab. While the index is building, the Status field reads Build in Progress. When the index is finished building, the Status field reads Active.

Note

Larger collections take longer to index. You will receive an email notification when your index is finished building.

You can run queries against the embedded document fields. This tutorial uses embeddedDocument and text operators inside the compound operator in the queries.

In this section, you will connect to your Atlas cluster and run the sample queries using the operators against the fields in the schools collection.


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


1

Warning

Navigation Improvements In Progress

We're currently rolling out a new and improved navigation experience. If the following steps don't match your view in the Atlas UI, see the preview documentation.

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

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

  3. If it's not already displayed, click Clusters in the sidebar.

    The Clusters page displays.

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.

    If you have no clusters, click Create cluster to create one. To learn more, see Create a Cluster.

  2. If your project has multiple clusters, select the cluster you want to use from the Select cluster dropdown, then click Go to Atlas Search.

    The Atlas Search page displays.

  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.

    The Atlas Search page displays.

  1. Click the cluster's name.

  2. Click the Atlas Search tab.

    The Atlas Search page displays.

3

Click the Query button to the right of the index to query.

4

Click Edit Query to view a default query syntax sample in JSON format.

5

Copy and paste the following query into the Query Editor, and then click the Search button in the Query Editor.

Note

The Search Tester doesn't support highlighting. So, use mongosh or a MongoDB driver to see highlighting information in the results.

To learn more about this query, see About this Tutorial.

1[
2 {
3 "$search": {
4 "index": "embedded-documents-tutorial",
5 "embeddedDocument": {
6 "path": "teachers",
7 "operator": {
8 "compound": {
9 "must": [{
10 "text": {
11 "path": "teachers.first",
12 "query": "John"
13 }
14 }],
15 "should":[{
16 "text": {
17 "path": "teachers.last",
18 "query": "Smith"
19 }
20 }]
21 }
22 }
23 }
24 }
25 }
26]
SCORE: 0.7830756902694702 _id: "1"
name: "Evergreen High"
mascot: "Jaguars"
teachers: Array
0: Object
first: "Jane"
last: "Earwhacker"
classes: Array
...
1: Object
first: "John"
last: "Smith"
classes: Array
...
clubs: Object
...
SCORE: 0.468008816242218 _id: "2"
name: "Lincoln High"
mascot: "Sharks"
teachers: Array
0: Object
first: "Jane"
last: "Smith"
classes: Array
...
1: Object
first: "John"
last: "Redman"
classes: Array
...
clubs: Object
...

To learn more about this query, see About this Tutorial.

1[
2 {
3 "$search": {
4 "index": "embedded-documents-tutorial",
5 "embeddedDocument": {
6 "path": "clubs.sports",
7 "operator": {
8 "queryString": {
9 "defaultPath": "clubs.sports.club_name",
10 "query": "dodgeball OR frisbee"
11 }
12 }
13 }
14 }
15 }
16]
score: 0.633669912815094 _id: 2
name: "Lincoln High"
mascot: "Sharks"
teachers: Array
...
clubs: Object
sports: Array (2)
0: Object
club_name: "dodgeball"
description: "provides students an opportunity
to play dodgeball by throwing balls t…"
1: Object
club_name: "martial arts"
description: "provides students an opportunity to learn self-defense or combat that …"
stem: Array (2)
...
score: 0.481589138507843 _id: 1
name: "Evergreen High"
mascot: "Jaguars"
teachers: Array
...
clubs: Object
sports: Array (2)
0: Object
club_name: "archery"
description: "provides students an opportunity to practice and hone the skill of usi…"
1: Object
club_name: "ultimate frisbee"
description: "provides students an opportunity to play frisbee and learn the basics …"
stem: Array (2)
...

To learn more about this query, see About this Tutorial.

[
{
$search: {
index: "embedded-documents-tutorial",
"embeddedDocument": {
"path": "teachers",
"operator": {
"compound": {
"must": [{
"embeddedDocument": {
"path": "teachers.classes",
"operator": {
"compound": {
"must": [{
"text": {
"path": "teachers.classes.grade",
"query": "12th"
}
},
{
"text": {
"path": "teachers.classes.subject",
"query": "science"
}
}]
}
}
}
}],
"should": [{
"text": {
"path": "teachers.last",
"query": "smith"
}
}]
}
}
}
}
}
]
SCORE: 0.9415585994720459
name: "Springfield High"
mascot: "Pumas"
teachers: Array
0: Object
first: "Jane"
last: "Smith"
classes: Array
0: Object
subject: "art of science"
grade: "12th"
1: Object
subject: "applied science and practical science"
grade: "9th"
2: Object
subject: "remedial math"
grade: "12th"
3: Object
subject: "science"
grade: "10th"
1: Object
first: "Bob"
last: "Green"
classes: Array
0: Object
subject: "science of art"
grade: "11th"
1: Object
subject: "art art art"
grade: "10th"
clubs: Object
...
SCORE: 0.7779859304428101 _id: "1"
name: "Evergreen High"
mascot: "Jaguars"
teachers: Array
0: Object
first: "Jane"
last: "Earwhacker"
classes: Array
0: Object
subject: "art"
grade: "9th"
1: Object
subject: "science"
grade: "12th"
1: Object
first: "John"
last: "Smith"
classes: Array
0: Object
subject: "math"
grade: "12th"
1: Object
subject: "art"
grade: "10th"
clubs: Object
...
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 local_school_district
switched to db local_school_district
3

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

1db.schools.aggregate({
2 "$search": {
3 "index": "embedded-documents-tutorial",
4 "embeddedDocument": {
5 "path": "teachers",
6 "operator": {
7 "compound": {
8 "must": [{
9 "text": {
10 "path": "teachers.first",
11 "query": "John"
12 }
13 }],
14 "should":[{
15 "text": {
16 "path": "teachers.last",
17 "query": "Smith"
18 }
19 }]
20 }
21 }
22 },
23 "highlight": {
24 "path": "teachers.last"
25 }
26 }
27},
28{
29 "$project": {
30 "_id": 1,
31 "teachers": 1,
32 "score": { $meta: "searchScore" },
33 "highlights": { "$meta": "searchHighlights" }
34 }
35})
1[
2 {
3 _id: 1,
4 teachers: [
5 {
6 first: 'Jane',
7 last: 'Earwhacker',
8 classes: [
9 { subject: 'art', grade: '9th' },
10 { subject: 'science', grade: '12th' }
11 ]
12 },
13 {
14 first: 'John',
15 last: 'Smith',
16 classes: [
17 { subject: 'math', grade: '12th' },
18 { subject: 'art', grade: '10th' }
19 ]
20 }
21 ],
22 score: 0.7830756902694702,
23 highlights: [
24 {
25 score: 1.4921371936798096,
26 path: 'teachers.last',
27 texts: [ { value: 'Smith', type: 'hit' } ]
28 }
29 ]
30 },
31 {
32 _id: 2,
33 teachers: [
34 {
35 first: 'Jane',
36 last: 'Smith',
37 classes: [
38 { subject: 'science', grade: '9th' },
39 { subject: 'math', grade: '12th' }
40 ]
41 },
42 {
43 first: 'John',
44 last: 'Redman',
45 classes: [ { subject: 'art', grade: '12th' } ]
46 }
47 ],
48 score: 0.468008816242218,
49 highlights: [
50 {
51 score: 1.4702850580215454,
52 path: 'teachers.last',
53 texts: [ { value: 'Smith', type: 'hit' } ]
54 }
55 ]
56 }
57]

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

To learn more about this query, see About this Tutorial.

1db.schools.aggregate(
2 {
3 "$search": {
4 "index": "embedded-documents-tutorial",
5 "embeddedDocument": {
6 "path": "clubs.sports",
7 "operator": {
8 "queryString": {
9 "defaultPath": "clubs.sports.club_name",
10 "query": "dodgeball OR frisbee"
11 }
12 }
13 }
14 }
15 },
16 {
17 "$project": {
18 "_id": 1,
19 "name": 1,
20 "clubs.sports": 1,
21 "score": { $meta: "searchScore" }
22 }
23 }
24)
1[
2 {
3 _id: 2,
4 name: 'Lincoln High',
5 clubs: {
6 sports: [
7 {
8 club_name: 'dodgeball',
9 description: 'provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves.'
10 },
11 {
12 club_name: 'martial arts',
13 description: 'provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons.'
14 }
15 ]
16 },
17 score: 0.633669912815094
18 },
19 {
20 _id: 1,
21 name: 'Evergreen High',
22 clubs: {
23 sports: [
24 {
25 club_name: 'archery',
26 description: 'provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment.'
27 },
28 {
29 club_name: 'ultimate frisbee',
30 description: 'provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes.'
31 }
32 ]
33 },
34 score: 0.481589138507843
35 }
36]

The two documents in the results show schools that offer clubs where students could play dodgeball or frisbee.

To learn more about this query, see About this Tutorial.

1db.schools.aggregate({
2 "$search": {
3 "index": "embedded-documents-tutorial",
4 "embeddedDocument": {
5 "path": "teachers",
6 "operator": {
7 "compound": {
8 "must": [{
9 "embeddedDocument": {
10 "path": "teachers.classes",
11 "operator": {
12 "compound": {
13 "must": [{
14 "text": {
15 "path": "teachers.classes.grade",
16 "query": "12th"
17 }
18 },
19 {
20 "text": {
21 "path": "teachers.classes.subject",
22 "query": "science"
23 }
24 }]
25 }
26 }
27 }
28 }],
29 "should": [{
30 "text": {
31 "path": "teachers.last",
32 "query": "smith"
33 }
34 }]
35 }
36 }
37 },
38 "highlight": {
39 "path": "teachers.classes.subject"
40 }
41 }
42},
43{
44 "$project": {
45 "_id": 1,
46 "teachers": 1,
47 "score": { $meta: "searchScore" },
48 "highlights": { "$meta": "searchHighlights" }
49 }
50})
1[
2 {
3 _id: 0,
4 teachers: [
5 {
6 first: 'Jane',
7 last: 'Smith',
8 classes: [
9 { subject: 'art of science', grade: '12th' },
10 {
11 subject: 'applied science and practical science',
12 grade: '9th'
13 },
14 { subject: 'remedial math', grade: '12th' },
15 { subject: 'science', grade: '10th' }
16 ]
17 },
18 {
19 first: 'Bob',
20 last: 'Green',
21 classes: [
22 { subject: 'science of art', grade: '11th' },
23 { subject: 'art art art', grade: '10th' }
24 ]
25 }
26 ],
27 score: 0.9415585994720459,
28 highlights: [
29 {
30 score: 0.7354040145874023,
31 path: 'teachers.classes.subject',
32 texts: [
33 { value: 'art of ', type: 'text' },
34 { value: 'science', type: 'hit' }
35 ]
36 },
37 {
38 score: 0.7871346473693848,
39 path: 'teachers.classes.subject',
40 texts: [
41 { value: 'applied ', type: 'text' },
42 { value: 'science', type: 'hit' },
43 { value: ' and practical ', type: 'text' },
44 { value: 'science', type: 'hit' }
45 ]
46 },
47 {
48 score: 0.7581484317779541,
49 path: 'teachers.classes.subject',
50 texts: [ { value: 'science', type: 'hit' } ]
51 },
52 {
53 score: 0.7189631462097168,
54 path: 'teachers.classes.subject',
55 texts: [
56 { value: 'science', type: 'hit' },
57 { value: ' of art', type: 'text' }
58 ]
59 }
60 ]
61 },
62 {
63 _id: 1,
64 teachers: [
65 {
66 first: 'Jane',
67 last: 'Earwhacker',
68 classes: [
69 { subject: 'art', grade: '9th' },
70 { subject: 'science', grade: '12th' }
71 ]
72 },
73 {
74 first: 'John',
75 last: 'Smith',
76 classes: [
77 { subject: 'math', grade: '12th' },
78 { subject: 'art', grade: '10th' }
79 ]
80 }
81 ],
82 score: 0.7779859304428101,
83 highlights: [
84 {
85 score: 1.502043604850769,
86 path: 'teachers.classes.subject',
87 texts: [ { value: 'science', type: 'hit' } ]
88 }
89 ]
90 }
91]

The two documents in the results contain teachers who teach 12th grade science. The document with _id: 0 contains a teacher with last name Smith who teaches 12th grade science.

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 local_school_district database, and then click the schools collection.

3

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

Pipeline Stage
Query

$search

{
"index": "embedded-documents-tutorial",
"embeddedDocument": {
"path": "teachers",
"operator": {
"compound": {
"must": [{
"text": {
"path": "teachers.first",
"query": "John"
}
}],
"should":[{
"text": {
"path": "teachers.last",
"query": "Smith"
}
}]
}
}
},
"highlight": {
"path": "teachers.last"
}
}

$project

{
"_id": 1,
"teachers": 1,
"score": { $meta: "searchScore" },
"highlights": { "$meta": "searchHighlights" }
}

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

1[
2 {
3 _id: 1,
4 teachers: [
5 {
6 first: 'Jane',
7 last: 'Earwhacker',
8 classes: [
9 { subject: 'art', grade: '9th' },
10 { subject: 'science', grade: '12th' }
11 ]
12 },
13 {
14 first: 'John',
15 last: 'Smith',
16 classes: [
17 { subject: 'math', grade: '12th' },
18 { subject: 'art', grade: '10th' }
19 ]
20 }
21 ],
22 score: 0.7830756902694702,
23 highlights: [
24 {
25 score: 1.4921371936798096,
26 path: 'teachers.last',
27 texts: [ { value: 'Smith', type: 'hit' } ]
28 }
29 ]
30 },
31 {
32 _id: 2,
33 teachers: [
34 {
35 first: 'Jane',
36 last: 'Smith',
37 classes: [
38 { subject: 'science', grade: '9th' },
39 { subject: 'math', grade: '12th' }
40 ]
41 },
42 {
43 first: 'John',
44 last: 'Redman',
45 classes: [ { subject: 'art', grade: '12th' } ]
46 }
47 ],
48 score: 0.468008816242218,
49 highlights: [
50 {
51 score: 1.4702850580215454,
52 path: 'teachers.last',
53 texts: [ { value: 'Smith', type: 'hit' } ]
54 }
55 ]
56 }
57]

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

To learn more about this query, see About this Tutorial.

Pipeline Stage
Query

$search

{
"index": "embedded-documents-tutorial",
embeddedDocument: {
path: "clubs.sports",
operator: {
queryString: {
defaultPath: "clubs.sports.club_name",
query: "dodgeball OR frisbee",
}
}
}
}

$project

{
"_id": 1,
"name": 1,
"clubs.sports": 1,
"score": { $meta: "searchScore" }
}

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

1[
2 {
3 _id: 2,
4 name: 'Lincoln High',
5 clubs: {
6 sports: [
7 {
8 club_name: 'dodgeball',
9 description: 'provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves.'
10 },
11 {
12 club_name: 'martial arts',
13 description: 'provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons.'
14 }
15 ]
16 },
17 score: 0.633669912815094
18 },
19 {
20 _id: 1,
21 name: 'Evergreen High',
22 clubs: {
23 sports: [
24 {
25 club_name: 'archery',
26 description: 'provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment.'
27 },
28 {
29 club_name: 'ultimate frisbee',
30 description: 'provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes.'
31 }
32 ]
33 },
34 score: 0.481589138507843
35 }
36]

The two documents in the results show schools that offer clubs where students could play dodgeball or frisbee.

To learn more about this query, see About this Tutorial.

Pipeline Stage
Query

$search

{
"index": "embedded-documents-tutorial",
"embeddedDocument": {
"path": "teachers",
"operator": {
"compound": {
"must": [{
"embeddedDocument": {
"path": "teachers.classes",
"operator": {
"compound": {
"must": [{
"text": {
"path": "teachers.classes.grade",
"query": "12th"
}
},
{
"text": {
"path": "teachers.classes.subject",
"query": "science"
}
}]
}
}
}
}],
"should": [{
"text": {
"path": "teachers.last",
"query": "smith"
}
}]
}
}
},
"highlight": {
"path": "teachers.classes.subject"
}
}

$project

{
"_id": 1,
"teachers": 1,
"score": { $meta: "searchScore" },
"highlights": { "$meta": "searchHighlights" }
}

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

1[
2 {
3 _id: 0,
4 teachers: [
5 {
6 first: 'Jane',
7 last: 'Smith',
8 classes: [
9 { subject: 'art of science', grade: '12th' },
10 {
11 subject: 'applied science and practical science',
12 grade: '9th'
13 },
14 { subject: 'remedial math', grade: '12th' },
15 { subject: 'science', grade: '10th' }
16 ]
17 },
18 {
19 first: 'Bob',
20 last: 'Green',
21 classes: [
22 { subject: 'science of art', grade: '11th' },
23 { subject: 'art art art', grade: '10th' }
24 ]
25 }
26 ],
27 score: 0.9415585994720459,
28 highlights: [
29 {
30 score: 0.7354040145874023,
31 path: 'teachers.classes.subject',
32 texts: [
33 { value: 'art of ', type: 'text' },
34 { value: 'science', type: 'hit' }
35 ]
36 },
37 {
38 score: 0.7871346473693848,
39 path: 'teachers.classes.subject',
40 texts: [
41 { value: 'applied ', type: 'text' },
42 { value: 'science', type: 'hit' },
43 { value: ' and practical ', type: 'text' },
44 { value: 'science', type: 'hit' }
45 ]
46 },
47 {
48 score: 0.7581484317779541,
49 path: 'teachers.classes.subject',
50 texts: [ { value: 'science', type: 'hit' } ]
51 },
52 {
53 score: 0.7189631462097168,
54 path: 'teachers.classes.subject',
55 texts: [
56 { value: 'science', type: 'hit' },
57 { value: ' of art', type: 'text' }
58 ]
59 }
60 ]
61 },
62 {
63 _id: 1,
64 teachers: [
65 {
66 first: 'Jane',
67 last: 'Earwhacker',
68 classes: [
69 { subject: 'art', grade: '9th' },
70 { subject: 'science', grade: '12th' }
71 ]
72 },
73 {
74 first: 'John',
75 last: 'Smith',
76 classes: [
77 { subject: 'math', grade: '12th' },
78 { subject: 'art', grade: '10th' }
79 ]
80 }
81 ],
82 score: 0.7779859304428101,
83 highlights: [
84 {
85 score: 1.502043604850769,
86 path: 'teachers.classes.subject',
87 texts: [ { value: 'science', type: 'hit' } ]
88 }
89 ]
90 }
91]

The two documents in the results contain teachers who teach 12th grade science. The document with _id: 0 contains a teacher with last name Smith who teaches 12th grade science.

1
  1. Create a new directory called embedded-documents-query and initialize your project with the dotnet new command.

    mkdir embedded-documents-query
    cd embedded-documents-query
    dotnet new console
  2. Add the .NET/C# Driver to your project as a dependency.

    dotnet add package MongoDB.Driver
2

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

1using MongoDB.Bson;
2using MongoDB.Bson.Serialization.Attributes;
3using MongoDB.Bson.Serialization.Conventions;
4using MongoDB.Driver;
5using MongoDB.Driver.Search;
6
7public class NestedArrayExample
8{
9 private const string MongoConnectionString = "<connection-string>";
10
11 public static void Main(string[] args)
12 {
13 // allow automapping of the camelCase database fields to our SchoolDocument
14 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
15 ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
16
17 // connect to your Atlas cluster
18 var mongoClient = new MongoClient(MongoConnectionString);
19 var districtSchoolsDatabase = mongoClient.GetDatabase("local_school_district");
20 var schoolsCollection = districtSchoolsDatabase.GetCollection<SchoolDocument>("schools");
21
22 // define variables for query
23 var compoundQuery = Builders<TeacherDocument>.Search.Compound()
24 .Must(Builders<TeacherDocument>.Search.Text(teacher => teacher.First, "John"))
25 .Should(Builders<TeacherDocument>.Search.Text(teacher => teacher.Last, "Smith"));
26 var opts = new SearchHighlightOptions<SchoolDocument>(school => school.Teachers.Select(teacher => teacher.Last));;
27
28 // define and run pipeline
29 var results = schoolsCollection.Aggregate()
30 .Search(Builders<SchoolDocument>.Search.EmbeddedDocument(
31 school => school.Teachers, compoundQuery), opts,
32 indexName: "embedded-documents-tutorial"
33 )
34 .Project<SchoolDocument>(Builders<SchoolDocument>.Projection
35 .Include(school => school.Name)
36 .Include(school => school.Mascot)
37 .Include(school => school.Teachers)
38 .MetaSearchScore(school => school.Score)
39 .MetaSearchHighlights("highlights"))
40 .ToList();
41
42 // print results
43 foreach (var school in results)
44 {
45 Console.WriteLine(school.ToJson());
46 }
47 }
48}
49
50[BsonIgnoreExtraElements]
51public class SchoolDocument
52{
53 public int Id { get; set; }
54 public string Name { get; set; }
55 public string Mascot { get; set; }
56 public TeacherDocument[] Teachers { get; set; }
57 [BsonElement("highlights")]
58 public List<SearchHighlight> Highlights { get; set; }
59 public double Score { get; set; }
60}
61
62[BsonIgnoreExtraElements]
63public class TeacherDocument
64{
65 public string First { get; set; }
66 public string Last { get; set; }
67 public ClassDocument[] Classes { get; set; }
68}
69
70[BsonIgnoreExtraElements]
71public class ClassDocument
72{
73 public string Subject { get; set; }
74 public string Grade { get; set; }
75}

To learn more about this query, see About this Tutorial.

1using MongoDB.Bson;
2using MongoDB.Bson.Serialization.Attributes;
3using MongoDB.Bson.Serialization.Conventions;
4using MongoDB.Driver;
5using MongoDB.Driver.Search;
6using System;
7using System.Collections.Generic;
8using System.Reflection.Emit;
9
10public class NestedArrayWithinObjectExample
11{
12 private const string MongoConnectionString = "<connection-string>";
13
14 public static void Main(string[] args)
15 {
16 // allow automapping of the camelCase database fields to our SchoolDocument
17 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
18 ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
19
20 // connect to your Atlas cluster
21 var mongoClient = new MongoClient(MongoConnectionString);
22 var districtSchoolsDatabase = mongoClient.GetDatabase("local_school_district");
23 var schoolsCollection = districtSchoolsDatabase.GetCollection<SchoolDocument>("schools");
24
25 // define variables for query
26 var queryStringQuery = Builders<ExtraCurricularDocument>.Search.QueryString(
27 sport => sport.ClubName, "dodgeball OR frisbee"
28 );
29
30 // define and run pipeline
31 var results = schoolsCollection.Aggregate()
32 .Search(Builders<SchoolDocument>.Search.EmbeddedDocument(
33 school => school.Clubs.Sports, queryStringQuery),
34 indexName: "embedded-documents-tutorial"
35 )
36 .Project<SchoolDocument>(Builders<SchoolDocument>.Projection
37 .Include(school => school.Clubs)
38 .Include(school => school.Name)
39 .Include(school => school.Id)
40 .MetaSearchScore(school => school.Score))
41 .ToList();
42
43 // print results
44 foreach (var school in results)
45 {
46 Console.WriteLine(school.ToJson());
47 }
48 }
49}
50
51[BsonIgnoreExtraElements]
52public class SchoolDocument
53{
54 public int Id { get; set; }
55 public string Name { get; set; }
56 public ClubDocument Clubs { get; set; }
57 public double Score { get; set; }
58}
59
60[BsonIgnoreExtraElements]
61public class ClubDocument
62{
63 public ExtraCurricularDocument[] Sports { get; set; }
64}
65
66[BsonIgnoreExtraElements]
67public class ExtraCurricularDocument
68{
69 [BsonElement("club_name")]
70 public string ClubName { get; set; }
71 public string Description { get; set; }
72}

To learn more about this query, see About this Tutorial.

1using MongoDB.Bson;
2using MongoDB.Bson.Serialization.Attributes;
3using MongoDB.Bson.Serialization.Conventions;
4using MongoDB.Driver;
5using MongoDB.Driver.Search;
6
7public class NestedArrayWithinArrayExample
8{
9 private const string MongoConnectionString = "<connection-string>";
10
11 public static void Main(string[] args)
12 {
13 // allow automapping of the camelCase database fields to our SchoolDocument
14 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
15 ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
16
17 // connect to your Atlas cluster
18 var mongoClient = new MongoClient(MongoConnectionString);
19 var districtSchoolsDatabase = mongoClient.GetDatabase("local_school_district");
20 var schoolsCollection = districtSchoolsDatabase.GetCollection<SchoolDocument>("schools");
21
22 // define variables for query
23 var mustQuery = Builders<ClassDocument>.Search.Compound()
24 .Must(Builders<ClassDocument>.Search.Text(classes => classes.Grade, "12th"), Builders<ClassDocument>.Search.Text(classes => classes.Subject, "science"));
25 var compoundQuery = Builders<TeacherDocument>.Search.Compound()
26 .Must(Builders<TeacherDocument>.Search.EmbeddedDocument(teacher => teacher.Classes, mustQuery))
27 .Should(Builders<TeacherDocument>.Search.Text(teacher => teacher.Last, "smith"));
28 var opts = new SearchHighlightOptions<SchoolDocument>("teachers.classes.subject");
29
30 // define and run pipeline
31 var results = schoolsCollection.Aggregate()
32 .Search(Builders<SchoolDocument>.Search.EmbeddedDocument(
33 school => school.Teachers, compoundQuery), opts,
34 indexName: "embedded-documents-tutorial"
35 )
36 .Project<SchoolDocument>(Builders<SchoolDocument>.Projection
37 .Include(school => school.Teachers)
38 .MetaSearchScore(school => school.Score)
39 .MetaSearchHighlights("highlights"))
40 .ToList();
41
42 // print results
43 foreach (var school in results)
44 {
45 Console.WriteLine(school.ToJson());
46 }
47 }
48}
49
50[BsonIgnoreExtraElements]
51public class SchoolDocument
52{
53 public int Id { get; set; }
54 public TeacherDocument[] Teachers { get; set; }
55 [BsonElement("highlights")]
56 public List<SearchHighlight> Highlights { get; set; }
57 public double Score { get; set; }
58}
59
60[BsonIgnoreExtraElements]
61public class TeacherDocument
62{
63 public string First { get; set; }
64 public string Last { get; set; }
65 public ClassDocument[] Classes { get; set; }
66}
67
68[BsonIgnoreExtraElements]
69public class ClassDocument
70{
71 public string Subject { get; set; }
72 public string Grade { get; set; }
73}
3

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

4
dotnet run embedded-documents-query.csproj
{
"_id" : 1,
"name" : "Evergreen High",
"mascot" : "Jaguars",
"teachers" : [{
"first" : "Jane",
"last" : "Earwhacker",
"classes" : [{ "
subject" : "art",
"grade" : "9th"
}, {
"subject" : "science",
"grade" : "12th"
}]
}, {
"first" : "John",
"last" : "Smith",
"classes" : [{
"subject" : "math",
"grade" : "12th"
}, {
"subject" : "art",
"grade" : "10th"
}]
}],
"highlights" : [{
"path" : "teachers.last",
"score" : 1.4921371936798096,
"texts" : [{ "type" : "Hit", "value" : "Smith" }]
}],
"score" : 0.78307569026947021
}
{
"_id" : 2,
"name" : "Lincoln High",
"mascot" : "Sharks",
"teachers" : [{
"first" : "Jane",
"last" : "Smith",
"classes" : [{
"subject" : "science",
"grade" : "9th"
}, {
"subject" : "math",
"grade" : "12th"
}]
}, {
"first" : "John",
"last" : "Redman",
"classes" : [{
"subject" : "art",
"grade" : "12th"
}]
}],
"highlights" : [{
"path" : "teachers.last",
"score" : 1.4702850580215454,
"texts" : [{ "type" : "Hit", "value" : "Smith" }]
}],
"score" : 0.46800881624221802
}
dotnet run embedded-documents-query.csproj
{
"_id" : 2,
"name" : "Lincoln High",
"clubs" : {
"sports" : [{
"club_name" : "dodgeball",
"description" : "provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves."
}, {
"club_name" : "martial arts",
"description" : "provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons."
}]
},
"score" : 0.63366991281509399
}
{
"_id" : 1,
"name" : "Evergreen High",
"clubs" : {
"sports" : [{
"club_name" : "archery",
"description" : "provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment."
}, {
"club_name" : "ultimate frisbee",
"description" : "provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes."
}]
},
"score" : 0.48158913850784302
}
dotnet run embedded-documents-query.csproj
{
"_id" : 0,
"teachers" : [{
"first" : "Jane",
"last" : "Smith",
"classes" : [{
"subject" : "art of science",
"grade" : "12th"
}, {
"subject" : "applied science and practical
science",
"grade" : "9th"
}, {
"subject" : "remedial math",
"grade" : "12th"
}, {
"subject" : "science",
"grade" : "10th"
}]
}, {
"first" : "Bob",
"last" : "Green",
"classes" : [{
"subject" : "science of art",
"grade" : "11th"
}, {
"subject" : "art art art",
"grade" : "10th"
}]
}],
"highlights" : [{
"path" : "teachers.classes.subject",
"score" : 0.73540401458740234,
"texts" : [
{ "type" : "Text", "value" : "art of " },
{ "type" : "Hit", "value" : "science" }
]
}, {
"path" : "teachers.classes.subject",
"score" : 0.78713464736938477,
"texts" : [
{ "type" : "Text", "value" : "applied " },
{ "type" : "Hit", "value" : "science" },
{ "type" : "Text", "value" : " and practical " },
{ "type" : "Hit", "value" : "science" }]
}, {
"path" : "teachers.classes.subject",
"score" : 0.7581484317779541,
"texts" : [{ "type" : "Hit", "value" : "science" }]
}, {
"path" : "teachers.classes.subject",
"score" : 0.7189631462097168,
"texts" : [
{ "type" : "Hit", "value" : "science" },
{ "type" : "Text", "value" : " of art" }
]
}],
"score" : 0.9415585994720459
}
{
"_id" : 1,
"teachers" : [{
"first" : "Jane",
"last" : "Earwhacker",
"classes" : [{
"subject" : "art",
"grade" : "9th"
}, {
"subject" : "science",
"grade" : "12th"
}]
}, {
"first" : "John",
"last" : "Smith",
"classes" : [{
"subject" : "math",
"grade" : "12th"
}, {
"subject" : "art",
"grade" : "10th"
}]
}],
"highlights" : [{
"path" : "teachers.classes.subject",
"score" : 1.502043604850769,
"texts" : [{ "type" : "Hit", "value" : "science" }]
}],
"score" : 0.77798593044281006
}
1
2

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

1package main
2
3import (
4 "context"
5 "fmt"
6
7 "go.mongodb.org/mongo-driver/v2/bson"
8 "go.mongodb.org/mongo-driver/v2/mongo"
9 "go.mongodb.org/mongo-driver/v2/mongo/options"
10)
11
12func main() {
13 // Connects to your Atlas cluster
14 client, err := mongo.Connect(options.Client().ApplyURI("<connection-string>"))
15 if err != nil {
16 panic(err)
17 }
18 defer client.Disconnect(context.TODO())
19
20 // Sets the namespace
21 collection := client.Database("local_school_district").Collection("schools")
22
23 searchStage := bson.D{{Key: "$search", Value: bson.M{
24 "index": "embedded-documents-tutorial",
25 "embeddedDocument": bson.M{
26 "path": "teachers", "operator": bson.M{
27 "compound": bson.M{
28 "must": bson.A{
29 bson.M{
30 "text": bson.D{
31 {Key: "path", Value: "teachers.first"},
32 {Key: "query", Value: "John"},
33 },
34 },
35 },
36 "should": bson.A{
37 bson.M{
38 "text": bson.D{
39 {Key: "path", Value: "teachers.last"},
40 {Key: "query", Value: "Smith"},
41 },
42 },
43 },
44 },
45 },
46 },
47 "highlight": bson.D{{Key: "path", Value: "teachers.last"}},
48 }}}
49
50 projectStage := bson.D{
51 {Key: "$project", Value: bson.D{
52 {Key: "teachers", Value: 1},
53 {Key: "score", Value: bson.D{{Key: "$meta", Value: "searchScore"}}},
54 {Key: "highlights", Value: bson.D{{Key: "$meta", Value: "searchHighlights"}}},
55 }},
56 }
57
58 // Runs the pipeline
59 cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{searchStage, projectStage})
60 if err != nil {
61 panic(err)
62 }
63
64 // Prints the results
65 var results []bson.D
66 if err = cursor.All(context.TODO(), &results); err != nil {
67 panic(err)
68 }
69 for _, result := range results {
70 fmt.Println(result)
71 }
72}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1package main
2
3import (
4 "context"
5 "fmt"
6
7 "go.mongodb.org/mongo-driver/v2/bson"
8 "go.mongodb.org/mongo-driver/v2/mongo"
9 "go.mongodb.org/mongo-driver/v2/mongo/options"
10)
11
12func main() {
13 // Connects to your Atlas cluster
14 client, err := mongo.Connect(options.Client().ApplyURI("<connection-string>"))
15 if err != nil {
16 panic(err)
17 }
18 defer client.Disconnect(context.TODO())
19
20 // Sets the namespace
21 collection := client.Database("local_school_district").Collection("schools")
22
23 // Defines the pipeline stages
24 searchStage := bson.D{{Key: "$search", Value: bson.M{
25 "index": "embedded-documents-tutorial",
26 "embeddedDocument": bson.D{
27 {Key: "path", Value: "clubs.sports"},
28 {Key: "operator", Value: bson.D{
29 {Key: "queryString", Value: bson.D{
30 {Key: "defaultPath", Value: "clubs.sports.club_name"},
31 {Key: "query", Value: "dodgeball OR frisbee"},
32 }},
33 }},
34 },
35 }}}
36
37 projectStage := bson.D{
38 {Key: "$project", Value: bson.D{
39 {Key: "name", Value: 1},
40 {Key: "clubs.sports", Value: 1},
41 {Key: "score", Value: bson.D{
42 {Key: "$meta", Value: "searchScore"},
43 }},
44 }},
45 }
46
47 // Runs the pipeline
48 cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{searchStage, projectStage})
49 if err != nil {
50 panic(err)
51 }
52
53 // Prints the results
54 var results []bson.D
55 if err = cursor.All(context.TODO(), &results); err != nil {
56 panic(err)
57 }
58 for _, result := range results {
59 fmt.Println(result)
60 }
61}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1package main
2
3import (
4 "context"
5 "fmt"
6
7 "go.mongodb.org/mongo-driver/v2/bson"
8 "go.mongodb.org/mongo-driver/v2/mongo"
9 "go.mongodb.org/mongo-driver/v2/mongo/options"
10)
11
12func main() {
13 // Connects to your Atlas cluster
14 client, err := mongo.Connect(options.Client().ApplyURI("<connection-string>"))
15 if err != nil {
16 panic(err)
17 }
18 defer client.Disconnect(context.TODO())
19
20 // Sets the namespace
21 collection := client.Database("local_school_district").Collection("schools")
22
23 // Defines the pipeline stages
24 searchStage := bson.D{{Key: "$search", Value: bson.M{
25 "index": "embedded-documents-tutorial",
26 "embeddedDocument": bson.M{
27 "path": "teachers",
28 "operator": bson.M{
29 "compound": bson.M{
30 "must": bson.A{
31 bson.M{
32 "embeddedDocument": bson.M{
33 "path": "teachers.classes",
34 "operator": bson.M{
35 "compound": bson.M{
36 "must": bson.A{
37 bson.M{
38 "text": bson.D{
39 {Key: "path", Value: "teachers.classes.grade"},
40 {Key: "query", Value: "12th"},
41 },
42 },
43 bson.M{
44 "text": bson.D{
45 {Key: "path", Value: "teachers.classes.subject"},
46 {Key: "query", Value: "science"},
47 },
48 },
49 },
50 },
51 },
52 },
53 },
54 },
55 "should": bson.A{
56 bson.M{
57 "text": bson.D{
58 {Key: "path", Value: "teachers.last"},
59 {Key: "query", Value: "Smith"},
60 },
61 },
62 },
63 },
64 },
65 },
66 "highlight": bson.D{{Key: "path", Value: "teachers.classes.subject"}},
67 }}}
68
69 projectStage := bson.D{
70 {Key: "$project", Value: bson.D{
71 {Key: "teachers", Value: 1},
72 {Key: "score", Value: bson.D{{Key: "$meta", Value: "searchScore"}}},
73 {Key: "highlights", Value: bson.D{{Key: "$meta", Value: "searchHighlights"}}},
74 }},
75 }
76
77 // Runs the pipeline
78 cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{searchStage, projectStage})
79 if err != nil {
80 panic(err)
81 }
82
83 // Prints the results
84 var results []bson.D
85 if err = cursor.All(context.TODO(), &results); err != nil {
86 panic(err)
87 }
88 for _, result := range results {
89 fmt.Println(result)
90 }
91}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

3
go run basic-embedded-documents-search.go
1[
2 {_id 1}
3 {teachers [[
4 {first Jane}
5 {last Earwhacker}
6 {classes [[{subject art} {grade 9th}] [{subject science} {grade 12th}]]}
7 ] [
8 {first John}
9 {last Smith}
10 {classes [[{subject math} {grade 12th}] [{subject art} {grade 10th}]]}
11 ]]}
12 {score 0.7830756902694702}
13 {highlights [[
14 {score 1.4921371936798096}
15 {path teachers.last}
16 {texts [[{value Smith} {type hit}]]}
17 ]]}
18]
19[
20 {_id 2}
21 {teachers [[
22 {first Jane}
23 {last Smith}
24 {classes [[{subject science} {grade 9th}] [{subject math} {grade 12th}]]}
25 ] [
26 {first John}
27 {last Redman}
28 {classes [[{subject art} {grade 12th}]]}
29 ]]}
30 {score 0.468008816242218}
31 {highlights [[
32 {score 1.4702850580215454}
33 {path teachers.last}
34 {texts [[{value Smith} {type hit}]]}
35 ]]}
36]

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

go run complex-embedded-documents-search.go
1[
2 {_id 2}
3 {name Lincoln High}
4 {clubs [
5 {sports [
6 [
7 {club_name dodgeball}
8 {description provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves.}
9 ] [
10 {club_name martial arts}
11 {description provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons.}
12 ]
13 ]}
14 ]}
15 {score 0.633669912815094}
16]
17[
18 {_id 1}
19 {name Evergreen High}
20 {clubs [
21 {sports [
22 [
23 {club_name archery}
24 {description provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment.}
25 ] [
26 {club_name ultimate frisbee}
27 {description provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes.}
28 ]
29 ]}
30 ]}
31 {score 0.481589138507843}
32]

The two documents in the results show schools that offer clubs where students could play dodgeball or frisbee.

go run nested-embedded-documents-search.go
1[
2 {_id 0}
3 {teachers [[
4 {first Jane}
5 {last Smith}
6 {classes [[{subject art of science} {grade 12th}] [{subject applied science and practical science} {grade 9th}] [{subject remedial math} {grade 12th}] [{subject science} {grade 10th}]]}
7 ] [
8 {first Bob}
9 {last Green}
10 {classes [[{subject science of art} {grade 11th}] [{subject art art art} {grade 10th}]]}
11 ]]}
12 {score 0.9415585994720459}
13 {highlights [[
14 {score 0.7354040145874023}
15 {path teachers.classes.subject}
16 {texts [[{value art of } {type text}] [{value science} {type hit}]]}
17 ] [
18 {score 0.7871346473693848}
19 {path teachers.classes.subject}
20 {texts [[{value applied } {type text}] [{value science} {type hit}] [{value and practical } {type text}] [{value science} {type hit}]]}
21 ] [
22 {score 0.7581484317779541}
23 {path teachers.classes.subject}
24 {texts [[{value science} {type hit}]]}
25 ] [
26 {score 0.7189631462097168}
27 {path teachers.classes.subject}
28 {texts [[{value science} {type hit}] [{value of art} {type text}]]}
29 ]]}
30]
31[
32 {_id 1}
33 {teachers [[
34 {first Jane}
35 {last Earwhacker}
36 {classes [[{subject art} {grade 9th}] [{subject science} {grade 12th}]]}
37 ] [
38 {first John}
39 {last Smith}
40 {classes [[{subject math} {grade 12th}] [{subject art} {grade 10th}]]}
41 ]]}
42 {score 0.7779859304428101}
43 {highlights [[
44 {score 1.502043604850769}
45 {path teachers.classes.subject}
46 {texts [[{value science} {type hit}]]}
47 ]]}
48]

The two documents in the results contain teachers who teach 12th grade science. The document with _id: 0 contains a teacher with last name Smith who teaches 12th grade science.

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

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

1import java.util.Arrays;
2import java.util.List;
3
4import static com.mongodb.client.model.Aggregates.limit;
5import static com.mongodb.client.model.Aggregates.project;
6import static com.mongodb.client.model.Projections.*;
7import com.mongodb.client.MongoClient;
8import com.mongodb.client.MongoClients;
9import com.mongodb.client.MongoCollection;
10import com.mongodb.client.MongoDatabase;
11import org.bson.Document;
12
13public class BasicEmbeddedDocumentsSearch {
14 public static void main( String[] args ) {
15 // define clauses
16 List<Document> mustClause =
17 List.of(
18 new Document(
19 "text",
20 new Document("path", "teachers.first")
21 .append("query", "John")));
22 List<Document> shouldClause =
23 List.of(
24 new Document(
25 "text",
26 new Document("path", "teachers.last")
27 .append("query", "Smith")));
28
29 // define query
30 Document agg =
31 new Document("$search", new Document("index", "embedded-documents-tutorial")
32 .append("embeddedDocument",
33 new Document("path", "teachers")
34 .append("operator",
35 new Document("compound",
36 new Document("must", mustClause)
37 .append("should", shouldClause))))
38 .append("highlight", new Document("path", "teachers.last")));
39
40 // specify connection
41 String uri = "<connection-string>";
42
43 // establish connection and set namespace
44 try (MongoClient mongoClient = MongoClients.create(uri)) {
45 MongoDatabase database = mongoClient.getDatabase("local_school_district");
46 MongoCollection<Document> collection = database.getCollection("schools");
47
48 // run query and print results
49 collection.aggregate(Arrays.asList(agg,
50 limit(5),
51 project(Document.parse("{score: {$meta: 'searchScore'}, _id: 0, teachers: 1, highlights: {$meta: 'searchHighlights'}}"))))
52 .forEach(doc -> System.out.println(doc.toJson()));
53 }
54 }
55}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1import java.util.Arrays;
2import static com.mongodb.client.model.Aggregates.limit;
3import static com.mongodb.client.model.Aggregates.project;
4import static com.mongodb.client.model.Projections.computed;
5import static com.mongodb.client.model.Projections.fields;
6import static com.mongodb.client.model.Projections.include;
7import com.mongodb.client.MongoClient;
8import com.mongodb.client.MongoClients;
9import com.mongodb.client.MongoCollection;
10import com.mongodb.client.MongoDatabase;
11import org.bson.Document;
12
13public class ComplexEmbeddedDocumentQuery {
14 public static void main(String[] args) {
15 // connect to your Atlas cluster
16 String uri = "<connection-string>";
17
18 try (MongoClient mongoClient = MongoClients.create(uri)) {
19 // set namespace
20 MongoDatabase database = mongoClient.getDatabase("my_test");
21 MongoCollection<Document> collection = database.getCollection("schools");
22
23 // define pipeline
24 Document agg = new Document("$search",
25 new Document("embeddedDocument",
26 new Document("path", "clubs.sports")
27 .append("operator",
28 new Document("queryString",
29 new Document("defaultPath", "clubs.sports.club_name")
30 .append("query", "dodgeball OR frisbee")))));
31
32 // run pipeline and print results
33 collection.aggregate(Arrays.asList(agg,
34 limit(5),
35 project(fields(
36 include("name", "clubs.sports"),
37 computed("score", new Document("$meta", "searchScore"))))))
38 .forEach(doc -> System.out.println(doc.toJson()));
39 }
40 }
41}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1import java.util.Arrays;
2import java.util.List;
3
4import static com.mongodb.client.model.Aggregates.limit;
5import static com.mongodb.client.model.Aggregates.project;
6import com.mongodb.client.MongoClient;
7import com.mongodb.client.MongoClients;
8import com.mongodb.client.MongoCollection;
9import com.mongodb.client.MongoDatabase;
10import org.bson.Document;
11
12public class NestedEmbeddedDocumentsSearch {
13 public static void main( String[] args ) {
14 // define clauses
15 List<Document> nestedMustClause =
16 List.of(
17 new Document(
18 "text",
19 new Document("path", "teachers.classes.grade")
20 .append("query", "12th")),
21 new Document("text",
22 new Document("path", "teachers.classes.subject")
23 .append("query", "science")));
24 List<Document> mustClause =
25 List.of(
26 new Document(
27 "embeddedDocument",
28 new Document("path", "teachers.classes")
29 .append("operator", new Document("compound",
30 new Document("must", nestedMustClause)))));
31 List<Document> shouldClause =
32 List.of(
33 new Document(
34 "text",
35 new Document("path", "teachers.last")
36 .append("query", "Smith")));
37
38 // define query
39 Document agg =
40 new Document(
41 "$search",
42 new Document("index", "embedded-documents-tutorial")
43 .append("embeddedDocument",
44 new Document("path", "teachers")
45 .append("operator",
46 new Document("compound",
47 new Document("must", mustClause)
48 .append("should", shouldClause))))
49 .append("highlight", new Document("path", "teachers.classes.subject")));
50
51 // specify connection
52 String uri = "<connection-string>";
53
54 // establish connection and set namespace
55 try (MongoClient mongoClient = MongoClients.create(uri)) {
56 MongoDatabase database = mongoClient.getDatabase("local_school_district");
57 MongoCollection<Document> collection = database.getCollection("schools");
58
59 // run query and print results
60 collection.aggregate(Arrays.asList(agg,
61 limit(5),
62 project(Document.parse("{score: {$meta: 'searchScore'}, _id: 0, teachers: 1, highlights: {$meta: 'searchHighlights'}}"))))
63 .forEach(doc -> System.out.println(doc.toJson()));
64 }
65 }
66}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

4
javac BasicEmbeddedDocumentsSearch.java
java BasicEmbeddedDocumentsSearch
1{
2 "teachers": [{
3 "first": "Jane",
4 "last": "Earwhacker",
5 "classes": [{
6 {"subject": "art", "grade": "9th"},
7 {"subject": "science", "grade": "12th"}
8 ]
9 }, {
10 "first": "John",
11 "last": "Smith",
12 "classes": [
13 {"subject": "math", "grade": "12th"},
14 {"subject": "art", "grade": "10th"}
15 ]
16 }],
17 "score": 0.7830756902694702,
18 "highlights": [{
19 "score": 1.4921371936798096,
20 "path": "teachers.last",
21 "texts": [{"value": "Smith", "type": "hit"}]
22 }]
23}
24{
25 "teachers": [{
26 "first": "Jane",
27 "last": "Smith",
28 "classes": [
29 {"subject": "science", "grade": "9th"},
30 {"subject": "math", "grade": "12th"}
31 ]
32 }, {
33 "first": "John",
34 "last": "Redman",
35 "classes": [
36 {"subject": "art", "grade": "12th"}
37 ]
38 }],
39 "score": 0.468008816242218,
40 "highlights": [{
41 "score": 1.4702850580215454,
42 "path": "teachers.last",
43 "texts": [{"value": "Smith", "type": "hit"}]
44 }]
45}

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

javac ComplexEmbeddedDocumentQuery.java
java ComplexEmbeddedDocumentQuery
1{
2 "_id": 2,
3 "name": "Lincoln High",
4 "clubs": {
5 "sports": [
6 {"club_name": "dodgeball", "description": "provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves."},
7 {"club_name": "martial arts", "description": "provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons."}
8 ]
9 },
10 "score": 0.633669912815094
11}
12{
13 "_id": 1,
14 "name": "Evergreen High",
15 "clubs": {
16 "sports": [
17 {"club_name": "archery", "description": "provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment."},
18 {"club_name": "ultimate frisbee", "description": "provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes."}
19 ]
20 },
21 "score": 0.481589138507843
22}

The two documents in the results show schools that offer clubs where students could play dodgeball or frisbee.

javac NestedEmbeddedDocumentsSearch.java
java NestedEmbeddedDocumentsSearch
1{
2 "teachers": [{
3 "first": "Jane",
4 "last": "Smith",
5 "classes": [
6 {"subject": "art of science", "grade": "12th"},
7 {"subject": "applied science and practical science", "grade": "9th"},
8 {"subject": "remedial math", "grade": "12th"},
9 {"subject": "science", "grade": "10th"}
10 ]
11 }, {
12 "first": "Bob",
13 "last": "Green",
14 "classes": [
15 {"subject": "science of art", "grade": "11th"},
16 {"subject": "art art art", "grade": "10th"}
17 ]
18 }],
19 "score": 0.9415585994720459,
20 "highlights": [{
21 "score": 0.7354040145874023,
22 "path": "teachers.classes.subject",
23 "texts": [
24 {"value": "art of ", "type": "text"},
25 {"value": "science", "type": "hit"}
26 ]
27 }, {
28 "score": 0.7871346473693848,
29 "path": "teachers.classes.subject",
30 "texts": [
31 {"value": "applied ", "type": "text"},
32 {"value": "science", "type": "hit"},
33 {"value": " and practical ", "type": "text"},
34 {"value": "science", "type": "hit"}
35 ]
36 }, {
37 "score": 0.7581484317779541,
38 "path": "teachers.classes.subject",
39 "texts": [
40 {"value": "science", "type": "hit"}
41 ]
42 }, {
43 "score": 0.7189631462097168,
44 "path": "teachers.classes.subject",
45 "texts": [
46 {"value": "science", "type": "hit"},
47 {"value": " of art", "type": "text"}
48 ]
49 }]
50}
51{
52 "teachers": [{
53 "first": "Jane",
54 "last": "Earwhacker",
55 "classes": [
56 {"subject": "art", "grade": "9th"},
57 {"subject": "science", "grade": "12th"}
58 ]
59 }, {
60 "first": "John",
61 "last": "Smith",
62 "classes": [
63 {"subject": "math", "grade": "12th"},
64 {"subject": "art", "grade": "10th"}
65 ]
66 }],
67 "score": 0.7779859304428101,
68 "highlights": [{
69 "score": 1.502043604850769,
70 "path": "teachers.classes.subject",
71 "texts": [{"value": "science", "type": "hit"}]
72 }]
73}

The two documents in the results contain teachers who teach 12th grade science. The document with _id: 0 contains a teacher with last name Smith who teaches 12th grade science.

1

mongodb-driver-kotlin-coroutine

4.10.0 or higher version

2
3

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

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
7
8fun main() {
9 // establish connection and set namespace
10 val uri = "<connection-string>"
11 val mongoClient = MongoClient.create(uri)
12 val database = mongoClient.getDatabase("local_school_district")
13 val collection = database.getCollection<Document>("schools")
14
15 runBlocking {
16 // define clauses
17 val mustClauses = listOf(
18 Document(
19 "text",
20 Document("path", "teachers.first").append("query", "John")
21 )
22 )
23
24 val shouldClauses = listOf(
25 Document(
26 "text",
27 Document("path", "teachers.last")
28 .append("query", "Smith")
29 )
30 )
31
32 // define query
33 val agg = Document(
34 "\$search", Document("index", "embedded-documents-tutorial")
35 .append(
36 "embeddedDocument",
37 Document("path", "teachers")
38 .append(
39 "operator",
40 Document(
41 "compound",
42 Document("must", mustClauses)
43 .append("should", shouldClauses)
44 )
45 )
46 )
47 .append("highlight", Document("path", "teachers.last"))
48 )
49
50 // run query and print results
51 val resultsFlow = collection.aggregate<Document>(
52 listOf(
53 agg,
54 limit(5),
55 project(fields(
56 excludeId(),
57 include("teachers"),
58 computed("score", Document("\$meta", "searchScore")),
59 computed("highlights", Document("\$meta", "searchHighlights"))
60 ))
61 )
62 )
63 resultsFlow.collect { println(it) }
64 }
65 mongoClient.close()
66}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

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
7
8fun main() {
9 // connect to your Atlas cluster
10 val uri = "<connection-string>"
11 val mongoClient = MongoClient.create(uri)
12
13 // set namespace
14 val database = mongoClient.getDatabase("local_school_district")
15 val collection = database.getCollection<Document>("schools")
16
17 runBlocking {
18 // define pipeline
19 val agg = Document(
20 "\$search",
21 Document("index", "embedded-documents-tutorial")
22 .append("embeddedDocument", Document("path", "clubs.sports")
23 .append(
24 "operator",
25 Document(
26 "queryString",
27 Document("defaultPath", "clubs.sports.club_name")
28 .append("query", "dodgeball OR frisbee")
29 )
30 )
31 )
32 )
33
34 // run pipeline and print results
35 val resultsFlow = collection.aggregate<Document>(
36 listOf(
37 agg,
38 limit(5),
39 project(
40 fields(
41 include("name", "clubs.sports"),
42 computed("score", Document("\$meta", "searchScore"))
43 )
44 )
45 )
46 )
47 resultsFlow.collect { println(it) }
48 }
49 mongoClient.close()
50}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

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
7
8fun main() {
9 // establish connection and set namespace
10 val uri = "<connection-string>"
11 val mongoClient = MongoClient.create(uri)
12 val database = mongoClient.getDatabase("local_school_district")
13 val collection = database.getCollection<Document>("schools")
14
15 runBlocking {
16 // define clauses
17 val nestedMustClauses = listOf(
18 Document("text", Document("path", "teachers.classes.grade")
19 .append("query", "12th")),
20 Document("text", Document("path", "teachers.classes.subject")
21 .append("query", "science"))
22 )
23
24 val mustClauses = listOf(
25 Document(
26 "embeddedDocument",
27 Document("path", "teachers.classes")
28 .append(
29 "operator", Document(
30 "compound",
31 Document("must", nestedMustClauses)
32 )
33 )
34 )
35 )
36
37 val shouldClauses = listOf(
38 Document(
39 "text",
40 Document("path", "teachers.last")
41 .append("query", "Smith")
42 )
43 )
44
45 // define query
46 val agg = Document(
47 "\$search",
48 Document("index", "embedded-documents-tutorial")
49 .append(
50 "embeddedDocument",
51 Document("path", "teachers")
52 .append(
53 "operator",
54 Document(
55 "compound",
56 Document("must", mustClauses)
57 .append("should", shouldClauses)
58 )
59 )
60 )
61 .append("highlight", Document("path", "teachers.classes.subject"))
62 )
63
64 // run query and print results
65 val resultsFlow = collection.aggregate<Document>(
66 listOf(
67 agg,
68 limit(5),
69 project(fields(
70 excludeId(),
71 include("teachers"),
72 computed("score", Document("\$meta", "searchScore")),
73 computed("highlights", Document("\$meta", "searchHighlights"))
74 ))
75 )
76 )
77 resultsFlow.collect { println(it) }
78 }
79 mongoClient.close()
80}

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

4

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

Document{{teachers=[Document{{first=Jane, last=Earwhacker, classes=[Document{{subject=art, grade=9th}}, Document{{subject=science, grade=12th}}]}}, Document{{first=John, last=Smith, classes=[Document{{subject=math, grade=12th}}, Document{{subject=art, grade=10th}}]}}], score=0.7830756902694702, highlights=[Document{{score=1.4921371936798096, path=teachers.last, texts=[Document{{value=Smith, type=hit}}]}}]}}
Document{{teachers=[Document{{first=Jane, last=Smith, classes=[Document{{subject=science, grade=9th}}, Document{{subject=math, grade=12th}}]}}, Document{{first=John, last=Redman, classes=[Document{{subject=art, grade=12th}}]}}], score=0.468008816242218, highlights=[Document{{score=1.4702850580215454, path=teachers.last, texts=[Document{{value=Smith, type=hit}}]}}]}}

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

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

Document{{_id=2, name=Lincoln High, clubs=Document{{sports=[Document{{club_name=dodgeball, description=provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves.}}, Document{{club_name=martial arts, description=provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons.}}]}}, score=0.633669912815094}}
Document{{_id=1, name=Evergreen High, clubs=Document{{sports=[Document{{club_name=archery, description=provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment.}}, Document{{club_name=ultimate frisbee, description=provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes.}}]}}, score=0.481589138507843}}

The two documents in the results show schools that offer clubs where students could play dodgeball or frisbee.

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

Document{{teachers=[Document{{first=Jane, last=Smith, classes=[Document{{subject=art of science, grade=12th}}, Document{{subject=applied science and practical science, grade=9th}}, Document{{subject=remedial math, grade=12th}}, Document{{subject=science, grade=10th}}]}}, Document{{first=Bob, last=Green, classes=[Document{{subject=science of art, grade=11th}}, Document{{subject=art art art, grade=10th}}]}}], score=0.9415585994720459, highlights=[Document{{score=0.7354040145874023, path=teachers.classes.subject, texts=[Document{{value=art of , type=text}}, Document{{value=science, type=hit}}]}}, Document{{score=0.7871346473693848, path=teachers.classes.subject, texts=[Document{{value=applied , type=text}}, Document{{value=science, type=hit}}, Document{{value= and practical , type=text}}, Document{{value=science, type=hit}}]}}, Document{{score=0.7581484317779541, path=teachers.classes.subject, texts=[Document{{value=science, type=hit}}]}}, Document{{score=0.7189631462097168, path=teachers.classes.subject, texts=[Document{{value=science, type=hit}}, Document{{value= of art, type=text}}]}}]}}
Document{{teachers=[Document{{first=Jane, last=Earwhacker, classes=[Document{{subject=art, grade=9th}}, Document{{subject=science, grade=12th}}]}}, Document{{first=John, last=Smith, classes=[Document{{subject=math, grade=12th}}, Document{{subject=art, grade=10th}}]}}], score=0.7779859304428101, highlights=[Document{{score=1.502043604850769, path=teachers.classes.subject, texts=[Document{{value=science, type=hit}}]}}]}}

The two documents in the results contain teachers who teach 12th grade science. The document with _id: 0 contains a teacher with last name Smith who teaches 12th grade science.

1
2

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

1const { MongoClient } = require("mongodb");
2
3// connect to your Atlas cluster
4const uri = "<connection-string>";
5const client = new MongoClient(uri);
6
7async function run() {
8 try {
9 await client.connect();
10
11 // set namespace
12 const database = client.db("local_school_district");
13 const coll = database.collection("schools");
14
15 // define pipeline
16 const agg = [
17 {
18 '$search': {
19 'index': 'embedded-documents-tutorial',
20 'embeddedDocument': {
21 'path': 'teachers',
22 'operator': {
23 'compound': {
24 'must': [
25 {
26 'text': {
27 'path': 'teachers.first',
28 'query': 'John'
29 }
30 }
31 ],
32 'should': [
33 {
34 'text': {
35 'path': 'teachers.last',
36 'query': 'Smith'
37 }
38 }
39 ]
40 }
41 }
42 },
43 'highlight': {
44 'path': 'teachers.last'
45 }
46 }
47 }, {
48 '$project': {
49 '_id': 1,
50 'teachers': 1,
51 'score': {
52 '$meta': 'searchScore'
53 },
54 'highlights': {
55 '$meta': 'searchHighlights'
56 }
57 }
58 }
59 ];
60
61 // run pipeline
62 const result = coll.aggregate(agg);
63
64 // print results
65 await result.forEach((doc) => console.dir(JSON.stringify(doc)));
66 } finally {
67 await client.close();
68 }
69}
70run().catch(console.dir);

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1const { MongoClient } = require("mongodb");
2
3// connect to your Atlas cluster
4const uri = "<connection-string>";
5const client = new MongoClient(uri);
6
7async function run() {
8 try {
9 await client.connect();
10
11 // set namespace
12 const database = client.db("local_school_district");
13 const coll = database.collection("schools");
14
15 // define pipeline
16 const agg = [
17 {
18 '$search': {
19 'index': 'embedded-documents-tutorial',
20 'embeddedDocument': {
21 'path': 'clubs.sports',
22 'operator': {
23 'queryString': {
24 'defaultPath': 'clubs.sports.club_name',
25 'query': 'dodgeball OR frisbee'
26 }
27 }
28 }
29 }
30 }, {
31 '$project': {
32 '_id': 1,
33 'name': 1,
34 'clubs.sports': 1,
35 'score': {
36 '$meta': 'searchScore'
37 }
38 }
39 }
40 ];
41
42 // run pipeline
43 const result = coll.aggregate(agg);
44
45 // print results
46 await result.forEach((doc) => console.dir(JSON.stringify(doc)));
47 } finally {
48 await client.close();
49 }
50}
51run().catch(console.dir);

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1const { MongoClient } = require("mongodb");
2
3// connect to your Atlas cluster
4const uri = "<connection-string>";
5
6const client = new MongoClient(uri);
7
8async function run() {
9 try {
10 await client.connect();
11
12 // set namespace
13 const database = client.db("local_school_district");
14 const coll = database.collection("schools");
15
16 // define pipeline
17 const agg = [
18 {
19 '$search': {
20 'index': 'embedded-documents-tutorial',
21 'embeddedDocument': {
22 'path': 'teachers',
23 'operator': {
24 'compound': {
25 'must': [
26 {
27 'embeddedDocument': {
28 'path': 'teachers.classes',
29 'operator': {
30 'compound': {
31 'must': [
32 {
33 'text': {
34 'path': 'teachers.classes.grade',
35 'query': '12th'
36 }
37 }, {
38 'text': {
39 'path': 'teachers.classes.subject',
40 'query': 'science'
41 }
42 }
43 ]
44 }
45 }
46 }
47 }
48 ],
49 'should': [
50 {
51 'text': {
52 'path': 'teachers.last',
53 'query': 'smith'
54 }
55 }
56 ]
57 }
58 }
59 },
60 'highlight': {
61 'path': 'teachers.classes.subject'
62 }
63 }
64 }, {
65 '$project': {
66 '_id': 1,
67 'teachers': 1,
68 'score': {
69 '$meta': 'searchScore'
70 },
71 'highlights': {
72 '$meta': 'searchHighlights'
73 }
74 }
75 }
76 ];
77
78 // run pipeline
79 const result = coll.aggregate(agg);
80
81 // print results
82 await result.forEach((doc) => console.dir(JSON.stringify(doc)));
83 } finally {
84 await client.close();
85 }
86}
87run().catch(console.dir);

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

3
node basic-embedded-documents-query.js
1{
2 "_id":1,
3 "teachers":[{
4 "first":"Jane",
5 "last":"Earwhacker",
6 "classes":[{"subject":"art","grade":"9th"},{"subject":"science","grade":"12th"}]
7 },{
8 "first":"John",
9 "last":"Smith",
10 "classes":[{"subject":"math","grade":"12th"},{"subject":"art","grade":"10th"}]
11 }],
12 "score":0.7830756902694702,
13 "highlights":[{
14 "score":1.4921371936798096,
15 "path":"teachers.last",
16 "texts":[{"value":"Smith","type":"hit"}]
17 }]
18}
19{
20 "_id":2,
21 "teachers":[{
22 "first":"Jane",
23 "last":"Smith",
24 "classes":[{"subject":"science","grade":"9th"},{"subject":"math","grade":"12th"}]
25 },{
26 "first":"John",
27 "last":"Redman",
28 "classes":[{"subject":"art","grade":"12th"}]
29 }],
30 "score":0.468008816242218,
31 "highlights":[{
32 "score":1.4702850580215454,
33 "path":"teachers.last",
34 "texts":[{"value":"Smith","type":"hit"}]
35 }]
36}

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

node complex-embedded-documents-query.js
1{
2 "_id":2,
3 "name":"Lincoln High",
4 "clubs":{
5 "sports":[{
6 "club_name":"dodgeball",
7 "description":"provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves."
8 },{
9 "club_name":"martial arts",
10 "description":"provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons."
11 }
12 ]},
13 "score":0.633669912815094
14}
15{
16 "_id":1,
17 "name":"Evergreen High",
18 "clubs":{
19 "sports":[{
20 "club_name":"archery",
21 "description":"provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment."
22 },{
23 "club_name":"ultimate frisbee",
24 "description":"provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes."
25 }]
26 },
27 "score":0.481589138507843
28}

The two documents in the results show schools that offer clubs where students could play dodgeball or frisbee.

node nested-embedded-documents-query.js
1{
2 "_id":0,
3 "teachers":[{
4 "first":"Jane",
5 "last":"Smith",
6 "classes":[{"subject":"art of science","grade":"12th"},{"subject":"applied science and practical science","grade":"9th"},{"subject":"remedial math","grade":"12th"},{"subject":"science","grade":"10th"}]
7 },{
8 "first":"Bob",
9 "last":"Green",
10 "classes":[{"subject":"science of art","grade":"11th"},{"subject":"art art art","grade":"10th"}]
11 }],
12 "score":0.9415585994720459,
13 "highlights":[{
14 "score":0.7354040145874023,
15 "path":"teachers.classes.subject",
16 "texts":[{"value":"art of ","type":"text"},{"value":"science","type":"hit"}]
17 },{
18 "score":0.7871346473693848,
19 "path":"teachers.classes.subject",
20 "texts":[{"value":"applied ","type":"text"},{"value":"science","type":"hit"},{"value":" and practical ","type":"text"},{"value":"science","type":"hit"}]
21 },{
22 "score":0.7581484317779541,
23 "path":"teachers.classes.subject",
24 "texts":[{"value":"science","type":"hit"}]
25 },{
26 "score":0.7189631462097168,
27 "path":"teachers.classes.subject",
28 "texts":[{"value":"science","type":"hit"},{"value":" of art","type":"text"}]
29 }]
30}
31{
32 "_id":1,
33 "teachers":[{
34 "first":"Jane",
35 "last":"Earwhacker",
36 "classes":[{"subject":"art","grade":"9th"},{"subject":"science","grade":"12th"}]
37 },{
38 "first":"John",
39 "last":"Smith",
40 "classes":[{"subject":"math","grade":"12th"},{"subject":"art","grade":"10th"}]
41 }],
42 "score":0.7779859304428101,
43 "highlights":[{
44 "score":1.502043604850769,
45 "path":"teachers.classes.subject",
46 "texts":[{"value":"science","type":"hit"}]
47 }]
48}

The two documents in the results contain teachers who teach 12th grade science. The document with _id: 0 contains a teacher with last name Smith who teaches 12th grade science.

1
2

To learn more about these queries, see About this Tutorial.

To learn more about this query, see About this Tutorial.

1import pymongo
2
3# connect to your Atlas cluster
4client = pymongo.MongoClient('<connection-string')
5
6# define pipeline
7pipeline = [
8 {
9 '$search': {
10 'index': 'embedded-documents-tutorial',
11 'embeddedDocument': {
12 'path': 'teachers',
13 'operator': {
14 'compound': {
15 'must': [
16 {
17 'text': {
18 'path': 'teachers.first',
19 'query': 'John'
20 }
21 }
22 ],
23 'should': [
24 {
25 'text': {
26 'path': 'teachers.last',
27 'query': 'Smith'
28 }
29 }
30 ]
31 }
32 }
33 },
34 'highlight': {
35 'path': 'teachers.last'
36 }
37 }
38 }, {
39 '$project': {
40 '_id': 1,
41 'teachers': 1,
42 'score': {
43 '$meta': 'searchScore'
44 },
45 'highlights': {
46 '$meta': 'searchHighlights'
47 }
48 }
49 }
50]
51
52# run pipeline
53result = client['local_school_district']['schools'].aggregate(pipeline)
54
55# print results
56for i in result:
57 print(i)

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

To learn more about this query, see About this Tutorial.

1import pymongo
2
3# connect to your Atlas cluster
4client = pymongo.MongoClient('<connection-string>')
5
6# define pipeline
7pipeline = [
8 {
9 '$search': {
10 'index': 'embedded-documents-tutorial',
11 'embeddedDocument': {
12 'path': 'clubs.sports',
13 'operator': {
14 'queryString': {
15 'defaultPath': 'clubs.sports.club_name',
16 'query': 'dodgeball OR frisbee'
17 }
18 }
19 }
20 }
21 }, {
22 '$project': {
23 '_id': 1,
24 'name': 1,
25 'clubs.sports': 1,
26 'score': {
27 '$meta': 'searchScore'
28 }
29 }
30 }
31]
32
33# run pipeline
34result = client['local_school_district']['schools'].aggregate(pipeline)
35
36# print results
37for i in result:
38 print(i)

To learn more about this query, see About this Tutorial.

1import pymongo
2
3# connect to your Atlas cluster
4client = pymongo.MongoClient('<connection-string>')
5
6# define pipeline
7pipeline = [
8 {
9 '$search': {
10 'index': 'embedded-documents-tutorial',
11 'embeddedDocument': {
12 'path': 'teachers',
13 'operator': {
14 'compound': {
15 'must': [
16 {
17 'embeddedDocument': {
18 'path': 'teachers.classes',
19 'operator': {
20 'compound': {
21 'must': [
22 {
23 'text': {
24 'path': 'teachers.classes.grade',
25 'query': '12th'
26 }
27 }, {
28 'text': {
29 'path': 'teachers.classes.subject',
30 'query': 'science'
31 }
32 }
33 ]
34 }
35 }
36 }
37 }
38 ],
39 'should': [
40 {
41 'text': {
42 'path': 'teachers.last',
43 'query': 'smith'
44 }
45 }
46 ]
47 }
48 }
49 },
50 'highlight': {
51 'path': 'teachers.classes.subject'
52 }
53 }
54 }, {
55 '$project': {
56 '_id': 1,
57 'teachers': 1,
58 'score': {
59 '$meta': 'searchScore'
60 },
61 'highlights': {
62 '$meta': 'searchHighlights'
63 }
64 }
65 }
66]
67
68# run pipeline
69result = client['local_school_district']['schools'].aggregate(pipeline)
70
71# print results
72for i in result:
73 print(i)

Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

3
python basic-embedded-documents-query.py
1{
2 '_id': 1,
3 'teachers': [{
4 'first': 'Jane',
5 'last': 'Earwhacker',
6 'classes': [{'subject': 'art', 'grade': '9th'}, {'subject': 'science', 'grade': '12th'}]
7 }, {
8 'first': 'John',
9 'last': 'Smith',
10 'classes': [{'subject': 'math', 'grade': '12th'}, {'subject': 'art', 'grade': '10th'}]
11 }],
12 'score': 0.7830756902694702,
13 'highlights': [{
14 'score': 1.4921371936798096,
15 'path': 'teachers.last',
16 'texts': [{'value': 'Smith', 'type': 'hit'}]
17 }]
18}
19{
20 '_id': 2,
21 'teachers': [{
22 'first': 'Jane',
23 'last': 'Smith',
24 'classes': [{'subject': 'science', 'grade': '9th'}, {'subject': 'math', 'grade': '12th'}]
25 }, {
26 'first': 'John',
27 'last': 'Redman',
28 'classes': [{'subject': 'art', 'grade': '12th'}]
29 }],
30 'score': 0.468008816242218,
31 'highlights': [{
32 'score': 1.4702850580215454,
33 'path': 'teachers.last',
34 'texts': [{'value': 'Smith', 'type': 'hit'}]
35 }]
36}

The two documents in the results contain teachers with the first name John. The document with _id: 1 ranks higher because it contains a teacher with the first name John who also has the last name Smith.

python complex-embedded-documents-query.py
1{
2 '_id': 2,
3 'name': 'Lincoln High',
4 'clubs': {
5 'sports': [{
6 'club_name': 'dodgeball',
7 'description': 'provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves.'
8 }, {
9 'club_name': 'martial arts',
10 'description': 'provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons.'
11 }]
12 },
13 'score': 0.633669912815094
14}
15{
16 '_id': 1,
17 'name': 'Evergreen High',
18 'clubs': {
19 'sports': [{
20 'club_name': 'archery',
21 'description': 'provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment.'
22 }, {
23 'club_name': 'ultimate frisbee', 'description': 'provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes.'
24 }]
25 },
26 'score': 0.481589138507843
27}
python advanced-embedded-documents-query.py
1{
2 '_id': 0,
3 'teachers': [{
4 'first': 'Jane',
5 'last': 'Smith',
6 'classes': [{'subject': 'art of science', 'grade': '12th'}, {'subject': 'applied science and practical science', 'grade': '9th'}, {'subject': 'remedial math', 'grade': '12th'}, {'subject': 'science', 'grade': '10th'}]
7 }, {
8 'first': 'Bob',
9 'last': 'Green',
10 'classes': [{'subject': 'science of art', 'grade': '11th'}, {'subject': 'art art art', 'grade': '10th'}]
11 }],
12 'score': 0.9415585994720459,
13 'highlights': [{
14 'score': 0.7354040145874023,
15 'path': 'teachers.classes.subject',
16 'texts': [{'value': 'art of ', 'type': 'text'}, {'value': 'science', 'type': 'hit'}]
17 }, {
18 'score': 0.7871346473693848,
19 'path': 'teachers.classes.subject',
20 'texts': [{'value': 'applied ', 'type': 'text'}, {'value': 'science', 'type': 'hit'}, {'value': ' and practical ', 'type': 'text'}, {'value': 'science', 'type': 'hit'}]
21 }, {
22 'score': 0.7581484317779541,
23 'path': 'teachers.classes.subject',
24 'texts': [{'value': 'science', 'type': 'hit'}]
25 }, {
26 'score': 0.7189631462097168,
27 'path': 'teachers.classes.subject',
28 'texts': [{'value': 'science', 'type': 'hit'}, {'value': ' of art', 'type': 'text'}]
29 }]
30 }
31 {
32 '_id': 1,
33 'teachers': [{
34 'first': 'Jane',
35 'last': 'Earwhacker',
36 'classes': [{'subject': 'art', 'grade': '9th'}, {'subject': 'science', 'grade': '12th'}]
37 }, {
38 'first': 'John',
39 'last': 'Smith',
40 'classes': [{'subject': 'math', 'grade': '12th'}, {'subject': 'art', 'grade': '10th'}]
41 }],
42 'score': 0.7779859304428101,
43 'highlights': [{
44 'score': 1.502043604850769,
45 'path': 'teachers.classes.subject',
46 'texts': [{'value': 'science', 'type': 'hit'}]
47 }]
48 }

You can run $searchMeta queries against the embedded document fields. In this section, you will connect to your Atlas cluster and run a sample query using the $searchMeta stage and facet on an embedded document field.

1

Warning

Navigation Improvements In Progress

We're currently rolling out a new and improved navigation experience. If the following steps don't match your view in the Atlas UI, see the preview documentation.

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

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

  3. If it's not already displayed, click Clusters in the sidebar.

    The Clusters page displays.

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.

    If you have no clusters, click Create cluster to create one. To learn more, see Create a Cluster.

  2. If your project has multiple clusters, select the cluster you want to use from the Select cluster dropdown, then click Go to Atlas Search.

    The Atlas Search page displays.

  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.

    The Atlas Search page displays.

  1. Click the cluster's name.

  2. Click the Atlas Search tab.

    The Atlas Search page displays.

3

Click the Query button to the right of the index to query.

4

Click Edit Query to view a default query syntax sample in JSON format.

5

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

Copy and paste the following query into the Query Editor, and then click the Search button in the Query Editor.

1[
2 {
3 "$searchMeta": {
4 "index": "embedded-documents-tutorial",
5 "facet": {
6 "operator": {
7 "text":{
8 "path": "name",
9 "query": "High"
10 }
11 },
12 "facets": {
13 "gradeFacet": {
14 "type": "string",
15 "path": "teachers.classes.grade"
16 }
17 }
18 }
19 }
20 }
21]
count: Object
lowerBound: 3
facet: Object
gradeFacet: Object
buckets: Array (4)
0: Object
_id: "12th"
count: 3
1: Object
_id: "9th"
count : 3
2: Object
_id: "10th"
count: 2
3: Object
_id: "11th"
count: 1
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 local_school_district
switched to db local_school_district
3

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1db.schools.aggregate({
2 "$searchMeta": {
3 "index": "embedded-documents-tutorial",
4 "facet": {
5 "operator": {
6 "text":{
7 "path": "name",
8 "query": "High"
9 }
10 },
11 "facets": {
12 "gradeFacet": {
13 "type": "string",
14 "path": "teachers.classes.grade"
15 }
16 }
17 }
18 }
19})
1[
2 {
3 count: { lowerBound: Long('3') },
4 facet: {
5 gradeFacet: {
6 buckets: [
7 { _id: '12th', count: Long('3') },
8 { _id: '9th', count: Long('3') },
9 { _id: '10th', count: Long('2') },
10 { _id: '11th', count: Long('1') }
11 ]
12 }
13 }
14 }
15]

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

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 local_school_district database, and then click the schools collection.

3

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

Pipeline Stage
Query

$searchMeta

{
"index": "embedded-embedded-documents-tutorial",
"facet": {
"operator": {
"text":{
"path": "name",
"query": "High"
}
},
"facets": {
"gradeFacet": {
"type": "string",
"path": "teachers.classes.grade"
}
}
}
}

MongoDB Compass displays the following in the results:

1count: Object
2 lowerBound: 3
3facet: Object
4 gradeFacet: Object
5 buckets: Array (4)
6 0: Object
7 _id: "12th"
8 count: 3
9 1: Object
10 _id: "9th"
11 count : 3
12 2: Object
13 _id: "10th"
14 count: 2
15 3: Object
16 _id: "11th"
17 count: 1

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

1
  1. Create a new directory called embedded-documents-query and initialize your project with the dotnet new command.

    mkdir embedded-documents-facet-query
    cd embedded-documents-facet-query
    dotnet new console
  2. Add the .NET/C# Driver to your project as a dependency.

    dotnet add package MongoDB.Driver
2

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1using MongoDB.Bson;
2using MongoDB.Bson.Serialization.Attributes;
3using MongoDB.Bson.Serialization.Conventions;
4using MongoDB.Driver;
5
6public class EmbeddedDocumentsFacetExample
7{
8 private const string MongoConnectionString = "<connection-string>";
9
10 public static void Main(string[] args)
11 {
12 // allow automapping of the camelCase database fields to our MovieDocument
13 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
14 ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
15
16 // connect to your Atlas cluster
17 var mongoClient = new MongoClient(MongoConnectionString);
18 var districtDatabase = mongoClient.GetDatabase("local_school_district");
19 var schoolCollection = districtDatabase.GetCollection<SchoolDocument>("schools");
20
21 // define and run pipeline
22 var results = schoolCollection.Aggregate()
23 .SearchMeta(Builders<SchoolDocument>.Search.Facet(
24 Builders<SchoolDocument>.Search.Text(school => school.Name, "High"),
25 Builders<SchoolDocument>.SearchFacet.String("gradeFacet", "teachers.classes.grade")),
26 indexName: "embedded-documents-tutorial")
27 .Single();
28
29 // print results
30 Console.WriteLine(results.ToJson());
31 }
32}
33
34[BsonIgnoreExtraElements]
35public class SchoolDocument
36{
37 public int Id { get; set; }
38 public string Name { get; set; }
39 public TeacherDocument[] Teachers { get; set; }
40}
41[BsonIgnoreExtraElements]
42public class TeacherDocument
43{
44 public ClassDocument[] Classes { get; set; }
45}
46[BsonIgnoreExtraElements]
47public class ClassDocument
48{
49 public string Grade { get; set; }
50}
3

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

4
dotnet run embedded-documents-facet-query.csproj
{
"count" : { "lowerBound" : NumberLong(3), "total" : null },
"facet" : {
"gradeFacet" : {
"buckets" : [
{ "_id" : "12th", "count" : NumberLong(3) },
{ "_id" : "9th", "count" : NumberLong(3) },
{ "_id" : "10th", "count" : NumberLong(2) },
{ "_id" : "11th", "count" : NumberLong(1) }
]
}
}
}

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

1
2

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1package main
2
3import (
4 "context"
5 "fmt"
6
7 "go.mongodb.org/mongo-driver/v2/bson"
8 "go.mongodb.org/mongo-driver/v2/mongo"
9 "go.mongodb.org/mongo-driver/v2/mongo/options"
10)
11
12func main() {
13 // connect to your Atlas cluster
14 client, err := mongo.Connect(options.Client().ApplyURI("<connection-string>"))
15 if err != nil {
16 panic(err)
17 }
18 defer client.Disconnect(context.TODO())
19
20 // set namespace
21 collection := client.Database("local_school_district").Collection("schools")
22
23 // define pipeline stages
24 searchStage := bson.D{
25 {Key: "$searchMeta", Value: bson.M{
26 "index": "embedded-documents-tutorial",
27 "facet": bson.M{
28 "operator": bson.M{
29 "text": bson.M{
30 "path": "name",
31 "query": "High",
32 },
33 },
34 "facets": bson.M{
35 "gradeFacet": bson.M{
36 "path": "teachers.classes.grade",
37 "type": "string",
38 },
39 },
40 },
41 }},
42 }
43
44 // run pipeline
45 cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{searchStage})
46 if err != nil {
47 panic(err)
48 }
49
50 // print results
51 var results []bson.D
52 if err = cursor.All(context.TODO(), &results); err != nil {
53 panic(err)
54 }
55 for _, result := range results {
56 fmt.Println(result)
57 }
58}
3

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

4
go run embedded-documents-facet-query.go
1[
2 {count [{lowerBound 3}]}
3 {facet [
4 {gradeFacet [
5 {buckets [
6 [{_id 12th} {count 3}]
7 [{_id 9th} {count 3}]
8 [{_id 10th} {count 2}]
9 [{_id 11th} {count 1}]
10 ]}
11 ]}
12 ]}
13]

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

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

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1import com.mongodb.client.MongoClient;
2import com.mongodb.client.MongoClients;
3import com.mongodb.client.MongoCollection;
4import com.mongodb.client.MongoDatabase;
5import org.bson.Document;
6import java.util.Arrays;
7
8public class FacetEmbeddedDocumentsSearch {
9 public static void main(String[] args) {
10 // connect to your Atlas cluster
11 String uri = "<connection-string>";
12 try (MongoClient mongoClient = MongoClients.create(uri)) {
13 // set namespace
14 MongoDatabase database = mongoClient.getDatabase("local_school_district");
15 MongoCollection<Document> collection = database.getCollection("schools");
16
17 // define pipeline
18 Document agg = new Document("$searchMeta",
19 new Document( "index", "embedded-documents-tutorial")
20 .append("facet",
21 new Document("operator",
22 new Document("text",
23 new Document("path", "name")
24 .append("query", "High")))
25 .append("facets",
26 new Document("gradeFacet",
27 new Document("type", "string").append("path", "teachers.classes.grade"))
28 )));
29 // run pipeline and print results
30 collection.aggregate(Arrays.asList(agg))
31 .forEach(doc -> System.out.println(doc.toJson()));
32 }
33 }
34}

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 FacetEmbeddedDocumentsSearch.java
java FacetEmbeddedDocumentsSearch
1{
2 "count": {"lowerBound": 3},
3 "facet": {
4 "gradeFacet": {
5 "buckets": [
6 {"_id": "12th", "count": 3},
7 {"_id": "9th", "count": 3},
8 {"_id": "10th", "count": 2},
9 {"_id": "11th", "count": 1}
10 ]
11 }
12 }
13}

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

1
  • MongoDB

    mongodb-driver-kotlin-coroutine

    To learn more, see Add MongoDB as a Dependency.

  • Serialization Library

    bson-kotlinx

    To learn more, see Add Serialization Library Dependencies.

2
3

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1import com.mongodb.kotlin.client.coroutine.MongoClient
2import kotlinx.coroutines.runBlocking
3import org.bson.Document
4
5fun main() {
6 // establish connection and set namespace
7 val uri = "<connection-string>"
8 val mongoClient = MongoClient.create(uri)
9 val database = mongoClient.getDatabase("local_school_district")
10 val collection = database.getCollection<Document>("schools")
11
12 runBlocking {
13
14 // define query
15 val agg = Document(
16 "\$searchMeta",
17 Document("index", "embedded-documents-tutorial")
18 .append("facet",
19 Document(
20 "operator",
21 Document(
22 "text",
23 Document("path", "name")
24 .append("query", "High")
25 )
26 )
27 .append(
28 "facets",
29 Document(
30 "gradeFacet",
31 Document("type", "string").append("path", "teachers.classes.grade")
32 )
33 )
34 )
35 )
36
37 // run query and print results
38 val resultsFlow = collection.aggregate<Document>(listOf(agg))
39 resultsFlow.collect { println(it) }
40 }
41 mongoClient.close()
42}
4

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

5

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

Document{{
count=Document{{lowerBound=3}},
facet=Document{{
gradeFacet=Document{{
buckets=[
Document{{_id=12th, count=3}},
Document{{_id=9th, count=3}},
Document{{_id=10th, count=2}},
Document{{_id=11th, count=1}}
]
}}
}}
}}

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

1
2

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1const { MongoClient } = require("mongodb");
2
3// connect to your Atlas cluster
4const uri = "<connection-string>";
5const client = new MongoClient(uri);
6
7async function run() {
8 try {
9 await client.connect();
10
11 // set namespace
12 const database = client.db("local_school_district");
13 const coll = database.collection("schools");
14
15 // define pipeline
16 const agg = [
17 {
18 "$searchMeta": {
19 "index": "embedded-documents-tutorial",
20 "facet": {
21 "operator": {
22 "text":{
23 "path": "name",
24 "query": "High"
25 }
26 },
27 "facets": {
28 "gradeFacet": {
29 "type": "string",
30 "path": "teachers.classes.grade"
31 }
32 }
33 }
34 }
35 }
36 ];
37
38 // run pipeline
39 const result = coll.aggregate(agg);
40
41 // print results
42 await result.forEach((doc) => console.dir(JSON.stringify(doc)));
43 } finally {
44 await client.close();
45 }
46}
47run().catch(console.dir);
3

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

4
node embedded-documents-facet-query.js
1{
2 "count":{"lowerBound":3},
3 "facet":{
4 "gradeFacet":{
5 "buckets":[
6 {"_id":"12th","count":3},
7 {"_id":"9th","count":3},
8 {"_id":"10th","count":2},
9 {"_id":"11th","count":1}
10 ]
11 }
12 }
13}

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

1
2

This query finds the high schools and requests a count of the number of schools that offer classes in each grade.

1import pymongo
2
3# connect to your Atlas cluster
4client = pymongo.MongoClient('<connection-string>')
5
6# define pipeline
7pipeline = [{"$searchMeta": {
8 "index": "embedded-documents-tutorial",
9 "facet": {
10 "operator": {
11 "text": {"path": "name", "query": 'High'}
12 },
13 "facets": {
14 "gradeFacet": {"type": "string", "path": "teachers.classes.grade"}
15 }
16 }
17}}]
18
19# run pipeline
20result = client["local_school_district"]["schools"].aggregate(pipeline)
21
22# print results
23for i in result:
24 print(i)
3

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

4
python embedded-documents-facet-query.py
1{
2 'count': {'lowerBound': 3},
3 'facet': {
4 'gradeFacet': {
5 'buckets': [
6 {'_id': '12th', 'count': 3},
7 {'_id': '9th', 'count': 3},
8 {'_id': '10th', 'count': 2},
9 {'_id': '11th', 'count': 1}
10 ]
11 }
12 }
13}

The results show that 3 schools offer classes for 12th and 9th grades, 2 schools offer classes for 10th grade, and 1 school offers classes for 11th grade. When you facet by a field inside an embedded document, the query returns count for the top-level parent document, which is the teachers field for this query.

Back

Search Non-Alphabetical Data as Strings