J'ai deux collections
Utilisateur
{
"_id" : ObjectId("584aac38686860d502929b8b"),
"name" : "John"
}
Rôle
{
"_id" : ObjectId("584aaca6686860d502929b8d"),
"role" : "Admin",
"userId" : "584aac38686860d502929b8b"
}
Je souhaite rejoindre cette collection basée sur le userId (dans role collection) - _id (dans user collection).
J'ai essayé la requête ci-dessous:
db.role.aggregate(
{
$lookup:
{
from: 'user',
localField: 'userId',
foreignField: '_id',
as: 'output'
}
}
);
Cela me donne les résultats escomptés tant que je stocke userId en tant que ObjectId. Lorsque mon userId est une chaîne, il n'y a aucun résultat. Ps: j'ai essayé
foreignField: '_id'.valueOf ()
et
foreignField: '_id'.toString ()
. Mais pas de chance de faire correspondre/rejoindre basé sur un champs ObjectId-string.
Toute aide serait appréciée.
Ceci n'est pas possible à partir de MongoDB 3.4. Cette fonctionnalité a déjà été demandée mais n'a pas encore été mise en œuvre. Voici les billets correspondants:
Pour l'instant, vous devrez stocker userId en tant que ObjectId
Vous pouvez utiliser $toObjectId
agrégation de mongodb 4.0 qui convertit String id
en ObjectId
db.role.aggregate([
{ "$lookup": {
"from": "user",
"let": { "userId": "$_id" },
"pipeline": [
{ "$addFields": { "userId": { "$toObjectId": "$userId" }}},
{ "$match": { "$expr": { "$eq": [ "$userId", "$$userId" ] } } }
],
"as": "output"
}}
])
Ou vous pouvez utiliser $toString
agrégation de mongodb 4.0 qui convertit ObjectId
en String
db.role.aggregate([
{ "$addFields": { "userId": { "$toString": "$_id" }}},
{ "$lookup": {
"from": "user",
"localField": "userId",
"foreignField": "userId",
"as": "output"
}}
])
Je pense que la réponse précédente a une erreur sur le cas '$ toObjectId'. L'instruction let
s'applique à la collection de base de données sur laquelle la fonction aggregate
est appelée (c'est-à-dire 'rôle') et non à la collection pointée par "de" (c'est-à-dire "utilisateur").
db.role.aggregate([
{ "$lookup": {
"let": { "userObjId": { "$toObjectId": "$userId" } },
"from": "user",
"pipeline": [
{ "$match": { "$expr": { "$eq": [ "$_id", "$$userObjId" ] } } }
],
"as": "userDetails"
}}
])
Ou
db.role.aggregate([
{ "$project": { "userObjId": { "$toObjectId": "$userId" } } },
{ "$lookup": {
"localField": "userObjId",
"from": "user",
"foreignField": "$_id",
"as": "userDetails"
}}
])
Et
db.user.aggregate([
{ "$project": { "userStrId": { "$toString": "$_id" }}},
{ "$lookup": {
"localField": "userStrId",
"from": "role",
"foreignField": "userId",
"as": "roleDetails"
}}
])