Para agentes de IA: hay un índice de documentación disponible en https://www.mongodb.com/es/docs/llms.txt; las versiones en Markdown de todas las páginas están disponibles agregando .md a cualquier ruta URL.
Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Docs Menu

Cómo ejecutar MongoDB Search queries contra campos en documentos incrustados

Este tutorial demuestra cómo indexar y ejecutar queries de MongoDB Search en campos que están dentro de un arreglo de documentos, incluso cuando el arreglo de documentos está anidado. Para permitir las consultas en estos campos, indexa los campos del documento como el tipo embeddedDocuments.

El tutorial de esta página demuestra consultas contra campos en los siguientes tipos de arreglos:

  • Arreglo de documentos.

  • Arreglo de documentos dentro de un documento.

  • Arreglo de documentos dentro de un arreglo de documentos.

Antes de comenzar, asegúrese de que su clúster cumpla con los requisitos descritos en los prerrequisitos.

Expande esta sección para obtener más información sobre la colección de muestras, el índice y las consultas utilizadas en este tutorial.

Para demostrar cómo ejecutar queries en documentos incrustados, este tutorial te guía a través de los siguientes pasos:

  1. Crear una colección de muestra llamada schools con documentos incrustados en el clúster.

  2. Configure un índice de búsqueda de MongoDB con campos embeddedDocuments configurados en las siguientes rutas:

    • teachers Campo

    • teachers.classes Campo

    • clubs.sports Campo

  3. ejecutar $search queries que búsqueda documentos incrustados en la colección schools usando el compuesto con el documento incrustado y el texto.

  4. Ejecutar un $searchMeta query en un campo de documento incrustado para obtener un recuento.

La colección de muestras schools contiene tres documentos. Cada documento contiene el name y mascot de la escuela, el ``primero`` y el last nombre de cada profesor, el classes que enseñan, incluyendo el subject y el grade, y los varios clubs disponibles.

El índice para esta colección especifica los siguientes documentos en arreglos:

  • Los documentos en los arreglos de las rutas teachers y teachers.classes se indexan como documentos incrustados, y los campos dentro de los documentos se indexan dinámicamente.

  • Los documentos en los arreglos de la ruta teachers también se indexan como el tipo documento para admitir resaltar, y los campos dentro de los documentos se indexan dinámicamente.

  • El documento en el campo clubs se indexa como tipo documento con mapeos dinámicos habilitados, y los arreglos de documentos en el campo clubs.sports se indexan como tipo embeddedDocuments con mapeos dinámicos habilitados.

Las queries de muestra buscan los documentos incrustados en la colección schools. Las queries utilizan las siguientes etapas del pipeline:

  • $search para buscar en la colección.

  • $project para incluir y excluir campos de la colección, y añadir un campo llamado score en los resultados. Para las queries que permiten resaltar, la etapa $project también añade un nuevo campo llamado highlights, que contiene la información de resaltar.

Los tutoriales demuestran las siguientes consultas:

Esta query demuestra una búsqueda en un campo dentro de un arreglo de documentos.

Buscar en la ruta teachers profesores con el nombre John y especificar una preferencia por profesores con el apellido Smith. También permite resaltar en el campo de nombre last.

Esta query demuestra una búsqueda en un campo dentro de un arreglo de documentos que está anidada dentro de un documento.

Busca escuelas que tengan clubes deportivos que ofrezcan a los estudiantes la oportunidad de jugar ya sea dodgeball o frisbee en la ruta clubs.sports.

Esta query demuestra una query compuesta que busca en campos dentro de los siguientes arreglos:

  • Arreglo de documentos.

  • Arreglo de documentos anidado dentro de un arreglo de documentos.

Busca escuelas que tengan un maestro enseñando 12th grado science clase en el camino teachers.classes, dando preferencia a las escuelas con maestros de apellido Smith que enseñan esa clase. También permite resaltar en el campo subject dentro del arreglo classes de los documentos, que está anidado dentro del arreglo teachers de documentos.

Nota

El tutorial para su clúster también incluye una consulta para obtener un recuento de la cantidad de escuelas que ofrecen clases en cada $searchMeta grado.

Este tutorial muestra ejemplos de consultas de búsqueda de MongoDB en campos de documentos incrustados. Para obtener más información sobre estas consultas, consulte Acerca de este tutorial.

You must begin by creating a collection named schools in an existing or new database on your 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
# Create a new directory and initialize the project
mkdir atlas-search-project && cd atlas-search-project
npm init -y
# Add the MongoDB Node.js Driver to your project
npm install mongodb

For detailed installation instructions, see the MongoDB Node Driver documentation.

2

Create and populate the schools collection:

1const { MongoClient } = require('mongodb');
2
3async function createSchoolsData() {
4 // Connection URI
5 const uri = '<connection-string>';
6
7 // Create a new MongoClient
8 const client = new MongoClient(uri);
9
10 try {
11 // Connect to the MongoDB server
12 await client.connect();
13
14 // Get the sample_mflix database
15 const database = client.db('local_school_district');
16
17 // Create the schools collection
18 try {
19 await database.createCollection('schools');
20 } catch (err) {
21 // Collection may already exist, which is fine
22 console.log(`Note: ${err.message}`);
23 }
24
25 // Get the collection
26 const collection = database.collection('schools');
27
28 // Create and insert the first document - Springfield High
29 const doc1 = {
30 _id: 0,
31 name: "Springfield High",
32 mascot: "Pumas",
33 teachers: [{
34 first: "Jane",
35 last: "Smith",
36 classes: [{
37 subject: "art of science",
38 grade: "12th"
39 },
40 {
41 subject: "applied science and practical science",
42 grade: "9th"
43 },
44 {
45 subject: "remedial math",
46 grade: "12th"
47 },
48 {
49 subject: "science",
50 grade: "10th"
51 }]
52 },
53 {
54 first: "Bob",
55 last: "Green",
56 classes: [{
57 subject: "science of art",
58 grade: "11th"
59 },
60 {
61 subject: "art art art",
62 grade: "10th"
63 }]
64 }],
65 clubs: {
66 stem: [
67 {
68 club_name: "chess",
69 description: "provides students opportunity to play the board game of chess informally and competitively in tournaments."
70 },
71 {
72 club_name: "kaboom chemistry",
73 description: "provides students opportunity to experiment with chemistry that fizzes and explodes."
74 }
75 ],
76 arts: [
77 {
78 club_name: "anime",
79 description: "provides students an opportunity to discuss, show, and collaborate on anime and broaden their Japanese cultural understanding."
80 },
81 {
82 club_name: "visual arts",
83 description: "provides students an opportunity to train, experiment, and prepare for internships and jobs as photographers, illustrators, graphic designers, and more."
84 }
85 ]
86 }
87 };
88
89 await collection.insertOne(doc1);
90
91 // Create and insert the second document - Evergreen High
92 const doc2 = {
93 _id: 1,
94 name: "Evergreen High",
95 mascot: "Jaguars",
96 teachers: [{
97 first: "Jane",
98 last: "Earwhacker",
99 classes: [{
100 subject: "art",
101 grade: "9th"
102 },
103 {
104 subject: "science",
105 grade: "12th"
106 }]
107 },
108 {
109 first: "John",
110 last: "Smith",
111 classes: [{
112 subject: "math",
113 grade: "12th"
114 },
115 {
116 subject: "art",
117 grade: "10th"
118 }]
119 }],
120 clubs: {
121 sports: [
122 {
123 club_name: "archery",
124 description: "provides students an opportunity to practice and hone the skill of using a bow to shoot arrows in a fun and safe environment."
125 },
126 {
127 club_name: "ultimate frisbee",
128 description: "provides students an opportunity to play frisbee and learn the basics of holding the disc and complete passes."
129 }
130 ],
131 stem: [
132 {
133 club_name: "zapped",
134 description: "provides students an opportunity to make exciting gadgets and explore electricity."
135 },
136 {
137 club_name: "loose in the chem lab",
138 description: "provides students an opportunity to put the scientific method to the test and get elbow deep in chemistry."
139 }
140 ]
141 }
142 };
143
144 await collection.insertOne(doc2);
145
146 // Create and insert the third document - Lincoln High
147 const doc3 = {
148 _id: 2,
149 name: "Lincoln High",
150 mascot: "Sharks",
151 teachers: [{
152 first: "Jane",
153 last: "Smith",
154 classes: [{
155 subject: "science",
156 grade: "9th"
157 },
158 {
159 subject: "math",
160 grade: "12th"
161 }]
162 },
163 {
164 first: "John",
165 last: "Redman",
166 classes: [{
167 subject: "art",
168 grade: "12th"
169 }]
170 }],
171 clubs: {
172 arts: [
173 {
174 club_name: "ceramics",
175 description: "provides students an opportunity to acquire knowledge of form, volume, and space relationships by constructing hand-built and wheel-thrown forms of clay."
176 },
177 {
178 club_name: "digital art",
179 description: "provides students an opportunity to learn about design for entertainment, 3D animation, technical art, or 3D modeling."
180 }
181 ],
182 sports: [
183 {
184 club_name: "dodgeball",
185 description: "provides students an opportunity to play dodgeball by throwing balls to eliminate the members of the opposing team while avoiding being hit themselves."
186 },
187 {
188 club_name: "martial arts",
189 description: "provides students an opportunity to learn self-defense or combat that utilize physical skill and coordination without weapons."
190 }
191 ]
192 }
193 };
194
195 await collection.insertOne(doc3);
196
197 console.log('Schools collection successfully created and populated.');
198 } catch (err) {
199 console.error(`Error: ${err.message}`);
200 process.exit(1);
201 } finally {
202 // Close the connection
203 await client.close();
204 }
205}
206
207// Run the function and handle any errors
208createSchoolsData().catch(console.error);

Replace <connection-string> with the connection string for your Atlas cluster or local Atlas deployment.

Your connection string should use the following format:

mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net

To learn more, see Connect to a Cluster via Client Libraries.

Your connection string should use the following format:

mongodb://localhost:<port-number>/?directConnection=true

To learn more, see Connection Strings.

3
node file-name.js
Schools collections successfully created and populated.
1
# Create a new directory and initialize the project
mkdir atlas-search-project && cd atlas-search-project
npm init -y
# Add the MongoDB Node.js Driver to your project
npm install mongodb

For detailed installation instructions, see the MongoDB Node Driver documentation.

2

Create a create-index.js file in your project directory, and copy and paste the following code into the file.

create-index.js
1const { MongoClient } = require("mongodb");
2
3// connect to your Atlas deployment
4const uri =
5 "<connection-string>";
6
7const client = new MongoClient(uri);
8
9async function run() {
10 try {
11
12 // set namespace
13 const database = client.db("local_school_district");
14 const collection = database.collection("schools");
15
16 // define your Atlas Search index
17 const index = {
18 name: "embedded-documents-tutorial",
19 definition: {
20 "mappings": {
21 "dynamic": true,
22 "fields": {
23 "clubs": {
24 "dynamic": true,
25 "fields": {
26 "sports": {
27 "dynamic": true,
28 "type": "embeddedDocuments"
29 }
30 },
31 "type": "document"
32 },
33 "teachers": [
34 {
35 "dynamic": true,
36 "fields": {
37 "classes": {
38 "dynamic": true,
39 "type": "embeddedDocuments"
40 }
41 },
42 "type": "embeddedDocuments"
43 },
44 {
45 "dynamic": true,
46 "fields": {
47 "classes": {
48 "dynamic": true,
49 "fields": {
50 "grade": {
51 "type": "token"
52 }
53 },
54 "type": "document"
55 }
56 },
57 "type": "document"
58 }
59 ]
60 }
61 }
62 }
63 }
64
65 // run the helper method
66 const result = await collection.createSearchIndex(index);
67 console.log("New index name: " + result);
68 } finally {
69 await client.close();
70 }
71}
72
73run().catch(console.dir);

Replace <connection-string> with the connection string for your Atlas cluster or local Atlas deployment.

Your connection string should use the following format:

mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net

To learn more, see Connect to a Cluster via Client Libraries.

Your connection string should use the following format:

mongodb://localhost:<port-number>/?directConnection=true

To learn more, see Connection Strings.

3
node create-index.js
New index name: embedded-documents-tutorial

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 cluster and run the sample queries using the operators against the fields in the schools collection.

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 to a Cluster via Client Libraries.

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 to a Cluster via Client Libraries.

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 to a Cluster via Client Libraries.

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.

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
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 to a Cluster via Client Libraries.

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.