J'ai une collection appelée article_category
qui stocke tous les article_id
appartient à la catégorie avec category_id
avec un format de données comme celui-ci.
Collection 1: article_category
{
"article_id": 2015110920343902,
"all_category_id": [5,8,10]
}
Ensuite, j'ai une autre collection appelée article
qui stocke tous mes messages
Collection 2: article
{
"title": "This is example rows in article collection"
"article_id": 2015110920343902,
},
{
"title": "Something change"
"article_id": 2015110920343903,
},
{
"title": "This is another rows",
"article_id": 2015110920343904,
}
Maintenant, je veux effectuer une requête MongoDB pour trouver title
avec regex
tandis que category_id
doit être égal à 8
. Voici ma requête mais ne fonctionne pas.
db.article.aggregate(
{
$match:
{
title:
{
$regex: /example/
}
}
},
{
$lookup:
{
from: "article_category",
pipeline: [
{ $match: { category_id: 8 } }
],
as: "article_category"
}
}
)
La requête ci-dessus n'affiche que les enregistrements qui correspondent par regex
mais ne correspondent pas par category_id
.
Une idée?
Tout d'abord, c'est all_category_id
, ne pas category_id
. Deuxièmement, vous ne liez pas d'articles - tous les documents auront exactement le même article_category
tableau. Enfin, vous souhaitez probablement filtrer les articles qui n'ont pas de catégorie correspondante. Le pipeline conditionnel devrait ressembler davantage à ceci:
db.article.aggregate([
{ $match: {
title: { $regex: /example/ }
} },
{ $lookup: {
from: "article_category",
let: {
article_id: "$article_id"
},
pipeline: [
{ $match: {
$expr: { $and: [
{ $in: [ 8, "$all_category_id" ] },
{ $eq: [ "$article_id", "$$article_id" ] }
] }
} }
],
as: "article_category"
} },
{ $match: {
$expr: { $gt: [
{ $size: "$article_category"},
0
] }
} }
] )
MISE À JOUR:
Si vous ne correspondez pas à article_id
, le $lookup
résultera avec un article_category
tableau à tous les articles.
Disons que votre article_category
la collection a un autre document:
{
"article_id": 0,
"all_category_id": [5,8,10]
}
Avec { $eq: [ "$article_id", "$$article_id" ] }
dans le pipeline le article_category
est
[
{
"article_id" : 2015110920343902,
"all_category_id" : [ 5, 8, 10 ]
}
]
sans pour autant:
[
{
"article_id" : 2015110920343902,
"all_category_id" : [ 5, 8, 10 ]
},
{
"article_id": 0,
"all_category_id": [ 5, 8, 10 ]
}
]
Si ce dernier est ce dont vous avez besoin, il serait beaucoup plus simple de trouver des demandes:
db.article.find({ title: { $regex: /example/ } })
et
db.article_category.find({ all_category_id: 8 })
Vous avez deux ou trois choses incorrectes ici. category_id
devrait être all_category_id
. Utilisez la condition de jointure dans $lookup
et déplacez le $match
en dehors de $lookup
scène avec $unwind
pour optimized
recherche.
Utilisation $project
avec exclusion pour supprimer le champ recherché de la réponse finale. Quelque chose comme {$project:{article_category:0}}
Essayer
db.article.aggregate([
{"$match":{"title":{"$regex":/example/}}},
{"$lookup":{
"from":"article_category",
"localField":"article_id",
"foreignField":"article_id",
"as":"article_category"
}},
{"$unwind":"$article_category"},
{"$match":{"article_category.all_category_id":8}}
])
Pour une sous-requête non corrélée, essayez
db.article.aggregate([
{"$match":{"title":{"$regex":/example/}}},
{"$lookup":{
"from":"article_category",
"pipeline":[{"$match":{"all_category_id":8}}],
"as":"categories"
}},
{"$match":{"categories":{"$ne":[]}}}
])