Menu Docs
Página inicial do Docs
/
Manual do banco de dados
/ / / /

$elemMatch (projeção)

Dica

$elemMatch (query)

$elemMatch

O operador $elemMatch limita o conteúdo de um campo <array> dos resultados da query para conter apenas o primeiro elemento que corresponda à condição $elemMatch.

O operador $ e também o operador $elemMatch projetam o primeiro elemento correspondente de uma array com base em uma condição.

O operador $ projeta o primeiro elemento de array correspondente de cada documento em uma collection com base em alguma condição da declaração de query.

O operador de projeção $elemMatch usa um argumento de condição explícita. Isso permite que você projete com base em uma condição que não esteja na query ou, se precisar projetar, com base em vários campos nos documentos incorporados da array. Consulte as Limitações de campos da array para ver um exemplo.

Independentemente da ordenação dos campos no documento, a projeção $elemMatch de um campo existente retorna o campo após as outras inclusões de campo existentes.

Por exemplo, considere uma collection players com o seguinte 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")
} )

A projeção a seguir retorna o campo games após os outros campos existentes incluídos na projeção, embora no documento o campo esteja listado antes dos campos joined e lastLogin:

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

Ou seja, a operação retorna o seguinte documento:

{
"_id" : ObjectId("5edef64a1c099fff6b033977"),
"joined" : ISODate("2020-01-01T00:00:00Z"),
"lastLogin" : ISODate("2020-05-01T00:00:00Z"),
"games" : [ { "game" : "abc", "score" : 8 } ]
}

Os exemplos no operador de projeção $elemMatch presumem uma coleção schools com os seguintes 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 },
]
}

Você pode modelar esses documentos utilizando as seguintes classes 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; }
}

A seguinte operação find() faz uma query de todos os documentos onde o valor do campo zipcode é "63109". A projeção $elemMatch retorna somente o primeiro elemento correspondente da array students em que o valor do campo school é de 102:

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

Para executar uma projeção $elemMatch ao usar o driver .NET/C#, chame o método ElemMatch() no construtor de projeção . Passe o nome do campo de array a ser projeto e o filtro a ser aplicado aos elementos de array.

O exemplo de código a seguir localiza todos os documentos nos quais o valor do campo Zipcode é "63109". Para cada documento correspondente, a projeção retorna os seguintes campos:

  • Id

  • O primeiro elemento da array Students no qual o valor do campo School aninhado tem o 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();

A operação retorna os seguintes documentos que têm um valor zipcode de "63109" e projeta a array students usando $elemMatch:

{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
  • Para o documento com _id igual a 1, a array students contém vários elementos com o campo school igual a 102. No entanto, a projeção $elemMatch retorna somente o primeiro elemento correspondente da array.

  • O documento com _id igual a 3 não contém o campo students no resultado, pois nenhum elemento em sua array students correspondeu à condição $elemMatch.

A projeção $elemMatch pode especificar critérios em vários campos.

A seguinte operação find() faz uma query de todos os documentos onde o valor do campo zipcode é "63109". A projeção inclui o primeiro elemento correspondente da array students onde o campo school tem um valor de 102 e o campo age é maior que 10:

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

O exemplo de código a seguir localiza todos os documentos nos quais o valor do campo Zipcode é "63109". Para cada documento correspondente, a projeção retorna os seguintes campos:

  • Id

  • O primeiro elemento da array Students no qual o valor do campo School aninhado tem o valor 102 e o campo Age tem um valor maior que 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();

A operação retorna os três documentos que possuem um valor zipcode de "63109":

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

O documento com _id igual a 3 não contém o campo students já que nenhum elemento da array corresponde aos critérios $elemMatch.

O argumento para $elemMatch corresponde aos elementos da array que $elemMatch está projetando. Se você especificar uma igualdade com um nome de campo para $elemMatch, ele tentará corresponder a objetos dentro da array. Por exemplo, $elemMatch tenta combinar objetos, em vez de valores escalares, dentro da array para o seguinte na projeção:

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();

Os exemplos anteriores retornam os documentos que têm um zipcode valor de "63109", mas esses documentos incluem apenas o _id campo porque a operação de projeção não encontrou elementos correspondentes.

Para corresponder valores escalares, use o operador de igualdade junto com o valor escalar que você deseja corresponder ({$eq: <scalar value>}). Por exemplo, a seguinte operação find() faz uma query de todos os documentos onde o valor do campo zipcode é "63109". A projeção inclui o elemento correspondente da array athletics onde o valor é basketball:

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

Para realizar uma operação $elemMatch em valores escalares de um array ao utilizar o driver .NET/C#, chame o método ElemMatch() no construtor de projeção. Passe o nome do campo array para o projeto e um filtro de igualdade para o campo "$eq" e o valor com o qual você deseja comparar.

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

A operação retorna os três documentos que têm o valor zipcode de "63109". Os documentos retornados incluem o campo _id e os elementos correspondentes do array athletics, se existirem.

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

O documento com _id igual a 3 é o único documento que corresponde aos critérios $elemMatch .

Dica

$ (projection) operador, operador

Voltar

$

Nesta página