我在mongoDB上有两个集合posts
和tags
。
这些集合之间存在多对多关系。
帖子可以属于某些标签,而标签可以包含一些帖子。
我正在寻找一种有效的查询方法,以将posts
与tags
连接起来,并保持postIds
的顺序。
如果数据架构不合适,我可以对其进行更改。
mongoDB版本为3.6.5
db.posts.insertMany([
{ _id: 'post001', title: 'this is post001' },
{ _id: 'post002', title: 'this is post002' },
{ _id: 'post003', title: 'this is post003' }
])
db.tags.insertMany([
{ _id: 'tag001', postIds: ['post003', 'post001', 'post002'] }
])
{
"_id": "tag001",
"postIds": [ "post003", "post001", "post002" ],
"posts": [
{ "_id": "post003", "title": "this is post003" },
{ "_id": "post001", "title": "this is post001" },
{ "_id": "post002", "title": "this is post002" }
]
}
我尝试了一个使用$lookup
的查询。
db.tags.aggregate([
{ $lookup: {
from: 'posts',
localField: 'postIds',
foreignField: '_id',
as: 'posts'
}}
])
但是我得到的结果与我想要的结果不同。
{
"_id": "tag001",
"postIds": [ "post003", "post001", "post002" ],
"posts": [
{ "_id": "post001", "title": "this is post001" },
{ "_id": "post002", "title": "this is post002" },
{ "_id": "post003", "title": "this is post003" }
]
}
答案 0 :(得分:2)
在MongoDB中,您将尝试对数据建模,以免完全避免联接(例如$lookup
中的联接),例如通过将tags
与posts
一起存储。
db.posts.insertMany([
{ _id: 'post001', title: 'this is post001', tags: [ "tag001", "tag002" ] },
{ _id: 'post002', title: 'this is post002', tags: [ "tag001" ] },
{ _id: 'post003', title: 'this is post003', tags: [ "tag002" ] }
])
有了这种结构,您可以像这样获得所需的结果:
db.posts.aggregate([{
$unwind: "$tags"
}, {
$group: {
_id: "$tags",
postsIds: {
$push: "$_id"
},
posts: {
$push: "$$ROOT"
}
}
}])
在这种情况下,我会怀疑您是否甚至需要结果中的postIds
字段,因为它仍然会包含在posts
数组中。
答案 1 :(得分:1)
您可以结合使用$map和$filter在投影阶段对posts
数组中的元素进行重新排序:
db.tags.aggregate([
{ $lookup: {
from: 'posts',
localField: 'postIds',
foreignField: '_id',
as: 'posts'
} },
{ $project: {
_id: 1,
postIds: 1,
posts: { $map: {
input: "$postIds",
as: "postId",
in: {
$arrayElemAt: [ { $filter: {
input: "$posts",
as: "post",
cond: { $eq: ["$$post._id", "$$postId"] }
} }, 0 ]
}
} }
} }
])
丢失的帖子将用null
填充,以使索引与postIds
保持一致。