繁体   English   中英

如何解决mongoDB中保持ID数组顺序的多对多关系

[英]How to resolve the many-to-many relation keeping the order of ID array in mongoDB

我在mongoDB上有两个收藏夹poststags 这些集合之间存在多对多关系。 一个帖子可以属于某些标签,而一个标签可以包含一些帖子。

我在寻找一个有效的查询方法加入poststags保持秩序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" }
  ]
}

在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数组中。

您可以结合使用$ 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保持一致。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM