Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$elemMatch (operador de proyección)

Tip

$elemMatch (operador de predicado de query)

$elemMatch

La $elemMatch operador limita el contenido de un campo <array> de los resultados de la query a contener solo el primer elemento que cumple la condición $elemMatch.

Tanto el operador $ como el $elemMatch operan proyectando el primer elemento coincidente de un arreglo en función de una condición.

El operador $ proyecta el primer elemento de un arreglo coincidente de cada documento en una colección, según alguna condición de la instrucción de query.

El operador de proyección $elemMatch toma un argumento explícito de condición. Esto permite proyectar lo que no está presente en la query, o que puedas proyectar varios campos en los documentos incrustados del arreglo. Consulta Limitaciones de campos de arreglos para un ejemplo.

Independientemente del orden de los campos en el documento, la proyección $elemMatch de un campo existente devuelve el campo después de las otras inclusiones de campos existentes.

Por ejemplo, considera una colección players con el siguiente documento:

db.players.insertOne( {
name: "player1",
games: [ { game: "abc", score: 8 }, { game: "xyz", score: 5 } ],
joined: new Date("2020-01-01"),
lastLogin: new Date("2020-05-01")
} )

La siguiente proyección retorna el campo games después de los otros campos existentes incluidos en la proyección, aunque en el documento, el campo está listado antes de los campos joined y lastLogin:

db.players.find( {}, { games: { $elemMatch: { score: { $gt: 5 } } }, joined: 1, lastLogin: 1 } )

Es decir, la operación devuelve el siguiente documento:

{
"_id" : ObjectId("5edef64a1c099fff6b033977"),
"joined" : ISODate("2020-01-01T00:00:00Z"),
"lastLogin" : ISODate("2020-05-01T00:00:00Z"),
"games" : [ { "game" : "abc", "score" : 8 } ]
}
  • Las operaciones db.collection.find() en vistas no con compatibles con el operador de proyección $elemMatch.

  • No puede especificar un operador del query $text en un $elemMatch.

Los ejemplos sobre el operador de proyección $elemMatch asumen una colección schools con los siguientes documentos:

{
_id: 1,
zipcode: "63109",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
},
{
_id: 2,
zipcode: "63110",
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
],
athletics: [ "swimming", "basketball", "football" ]
},
{
_id: 3,
zipcode: "63109",
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
],
athletics: [ "baseball", "basketball", "soccer" ]
},
{
_id: 4,
zipcode: "63109",
students: [
{ name: "barney", school: 102, age: 7 },
{ name: "ruth", school: 102, age: 16 },
]
}

Puedes modelar estos documentos usando las siguientes clases de C#:

public class School
{
public string Id { get; set; }
[BsonElement("zipcode")]
public string ZipCode { get; set; }
public Student[] Students { get; set; }
public string[] Athletics { get; set; }
}
public class Student
{
public string Id { get; set; }
public string Name { get; set; }
public int School { get; set; }
public int Age { get; set; }
}

La siguiente operación find() query para todos los documentos donde el valor del campo zipcode es "63109". La proyección $elemMatch devuelve solo el primer elemento coincidente del arreglo students donde el campo school tiene un valor de 102:

db.schools.find( { zipcode: "63109" },
{ students: { $elemMatch: { school: 102 } } } )

Para realizar una proyección de $elemMatch al usar el driver de .NET/C#, llama al método ElemMatch() en el generador de proyecciones. Pasa el nombre del campo del arreglo para proyectar y el filtro para aplicar a los elementos del arreglo.

El siguiente ejemplo de código encuentra todos los documentos en los que el valor del campo Zipcode es "63109". Para cada documento coincidente, la proyección devuelve los siguientes campos:

  • Id

  • El primer elemento del Students arreglo en el que el valor del campo anidado School tiene el valor 102

var results = schoolsCollection
.Find(s => s.ZipCode == "63109")
.Project(Builders<School>.Projection.ElemMatch(
field: school => school.Students,
filter: student => student.School == 102
)
).ToList();

La operación devuelve los siguientes documentos que tienen un valor de zipcode de "63109" y proyecta el arreglo students mediante $elemMatch:

{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
  • Para el documento con _id igual a 1, el arreglo students contiene varios elementos con el campo school igual a 102. Sin embargo, la proyección $elemMatch solo devuelve el primer elemento correspondiente del arreglo.

  • El documento con _id igual a 3 no contiene el campo students en el resultado ya que ningún elemento en su arreglo students coincidió con la condición $elemMatch.

La proyección $elemMatch puede especificar criterios en varios campos.

La siguiente operación find() consulta todos los documentos donde el valor del campo zipcode es "63109". La proyección incluye el primer elemento coincidente del arreglo students donde el campo school tiene un valor de 102 y el campo age es mayor que 10:

db.schools.find( { zipcode: "63109" },
{ students: { $elemMatch: { school: 102, age: { $gt: 10} } } } )

El siguiente ejemplo de código encuentra todos los documentos en los que el valor del campo Zipcode es "63109". Para cada documento coincidente, la proyección devuelve los siguientes campos:

  • Id

  • El primer elemento del arreglo Students en el que el valor del campo anidado School tiene el valor 102 y el campo Age tiene un valor superior a 10

var results = schoolsCollection
.Find(s => s.ZipCode == "63109")
.Project(Builders<School>.Projection.ElemMatch(
field: school => school.Students,
filter: student => (student.School == 102) && (student.Age > 10)
)
).ToList();

La operación devuelve los tres documentos que tienen un valor zipcode de "63109":

{ "_id" : 1, "students" : [ { "name" : "jess", "school" : 102, "age" : 11 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "ruth", "school" : 102, "age" : 16 } ] }

El documento con _id igual a 3 no contiene el campo students ya que ningún elemento del arreglo coincide con el criterio $elemMatch.

El argumento para $elemMatch se corresponde con los elementos del arreglo que $elemMatch está proyectando. Si se especifica una igualdad con un nombre de campo a $elemMatch, se intenta hacer coincidir objetos dentro del arreglo. Por ejemplo, $elemMatch intenta hacer coincidir objetos, en lugar de valores escalares, dentro del arreglo para lo siguiente en la proyección:

db.schools.find( { zipcode: "63109" },
{ athletics: { $elemMatch: { athletics: "basketball" } } })
var results = schoolsCollection
.Find(s => s.ZipCode == "63109")
.Project(Builders<School>.Projection.ElemMatch(
"athletics",
Builders<School>.Filter.Eq("athletics", "basketball"))
).ToList();

Los ejemplos precedentes devuelven los documentos que tienen un valor de zipcode de "63109", pero estos documentos sólo incluyen el campo _id porque la operación de proyección no encontró elementos coincidentes.

Para hacer coincidir los valores escalares, utilizar el operador de igualdad junto con el valor escalar que se desea igualar ({$eq: <scalar value>}). Por ejemplo, la siguiente operación find() consulta todos los documentos en los que el valor del campo zipcode es "63109". La proyección incluye el elemento de coincidencia del arregloathletics donde el valor es basketball:

db.schools.find( { zipcode: "63109" },
{ athletics: { $elemMatch: { $eq: "basketball" } } })

Para realizar una operación $elemMatch contra los valores escalares de un arreglo cuando se utiliza el driver .NET/C#, ejecuta el método ElemMatch() en el desarrollador de proyección. Pasa el nombre del campo de arreglo a proyectar y un filtro de igualdad para el campo "$eq" y el valor con el que deseas compararlo.

var results = schoolsCollection
.Find(s => s.ZipCode == "63109")
.Project(Builders<School>.Projection.ElemMatch(
field: "athletics",
filter: Builders<School>.Filter.Eq("$eq", "basketball"))
).ToList();

La operación devuelve los tres documentos que tienen un valor de zipcode de "63109". Los documentos devueltos incluyen el campo _id y los elementos coincidentes del arreglo athletics, si los hay.

[
{ _id: 1 },
{ _id: 3, athletics: [ 'basketball' ] },
{ _id: 4 }
]

El documento con _id igual a 3 es el único documento que cumple con los criterios $elemMatch.

Tip

Volver

$

En esta página