J'ai le prochain code mongo:
db.users.aggregate([
{
$match: {
$and: [
{ UserName: { $eq: 'administrator' } },
{ 'Company.CompanyName': { $eq: 'test' } }
]
}
},
{
$lookup: {
from: "companies",
localField: "CompanyID",
foreignField: "CompanyID",
as: "Company"
}
},
])
Le $lookup
une partie du code fonctionne très bien. J'ai obtenu le résultat suivant:
Mais si j'ajoute $match
au code, il n'apporte rien.
J'ai trouvé que le problème venait de la deuxième correspondance: { 'Company.CompanyName': { $eq: 'test' } }
, mais je ne peux pas réaliser ce qui ne va pas. Des idées?
MISE À JOUR:
J'avais aussi essayé $unwind
sur le $lookup
résultat, mais pas de chance:
db.users.aggregate([
{
$match: {
$and: [
{ UserName: { $eq: 'administrator' } },
{ 'Company.CompanyName': { $eq: 'edt5' } }
]
}
},
{ unwind: '$Company' },
{
$lookup: {
from: 'companies',
localField: 'CompanyID',
foreignField: 'CompanyID',
as: 'Company'
}
},
])
Avec MongoDB 3.4, vous pouvez exécuter un pipeline d'agrégation qui utilise le $addFields
pipeline et un $filter
opérateur pour renvoyer uniquement le tableau Company
avec des éléments qui correspondent à la condition donnée. Vous pouvez ensuite envelopper le $filter
expression avec le $arrayElemAt
opérateur pour renvoyer un seul document qui incorpore essentiellement $unwind
fonctionnalité en aplatissant le tableau.
Suivez cet exemple pour comprendre le concept ci-dessus:
db.users.aggregate([
{ "$match": { "UserName": "administrator" } },
{
"$lookup": {
"from": 'companies',
"localField": 'CompanyID',
"foreignField": 'CompanyID',
"as": 'Company'
}
},
{
"$addFields": {
"Company": {
"$arrayElemAt": [
{
"$filter": {
"input": "$Company",
"as": "comp",
"cond": {
"$eq": [ "$$comp.CompanyName", "edt5" ]
}
}
}, 0
]
}
}
}
])
La réponse ci-dessous concerne mongoDB 3.6 ou version ultérieure.
Étant donné que:
users
avec un champ CompanyID
et une collection de companies
avec un champ CompanyID
vous voulez rechercher Companies
sur Users
en faisant correspondre CompanyID
, où en plus:
User.UserName
est égal à administrator
Company
sur User
doit correspondre à la condition: CompanyName
est égal à edt5
La requête suivante fonctionnera pour vous:
db.users.aggregate([
{ $match: { UserName: 'administrator' } },
{
$lookup: {
from: 'companies',
as: 'Company',
let: { CompanyID: '$CompanyID' },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ['$CompanyID', '$$CompanyID'] },
{ $eq: ['$CompanyName', 'edt5'] },
]
}
}
}
]
}
},
])
Explication: C'est la façon d'effectuer des requêtes de jointure gauche avec des conditions plus complexes qu'une simple correspondance d'égalité de champ étranger/local.
Au lieu d'utiliser localField
et foreignField
, vous utilisez:
let
option où vous pouvez mapper des champs locaux à des variables,pipeline
option où vous pouvez spécifier l'agrégation Array
.Dans pipeline
, vous pouvez utiliser $match
filtre, avec $expr
, où vous pouvez réutiliser des variables définies précédemment dans let
.