【问题标题】:How to find by referenced Object's property in Mongoose?如何在 Mongoose 中通过引用对象属性查找?
【发布时间】:2020-08-16 00:52:45
【问题描述】:

我有两个模型,使用 Mongoose Schema 制作。

Book {
    title: String,
    chapters: [{
        type: Schema.Types.ObjectId,
        ref: 'chapter'
    }],
}

Chapter {
    title: String,
    status: String,
    book: {
        type: Schema.Types.ObjectId,
        ref: 'book'
    },
}

我想找到与"status":"unfinished" 有章节的Books。实现这一目标的最有效方法是什么?由于 Book 模型存储 ObjectIds,如何进行查找查询,以便直接从 DB 中获取过滤后的结果?

【问题讨论】:

    标签: node.js mongodb mongoose mongodb-query


    【解决方案1】:

    我认为最好的方法是去规范化你的模式,因为book 将有一个limited amount of chapters 并且一个章节可以属于at most one book,我们可以像这样存储模式这个

    Book {
        title: String,
        chapters: [{
             title: String,
             status: String,
        }],
    }
    

    使用此架构,我们可以在“chapters.status”上创建一个索引,并且无需$lookup,只需在单个查询中即可获得答案。

    db.books.find({'chapters.status': 'unfinished'});
    

    但无论如何,您仍然需要使用上述架构,我们始终可以选择$lookup

    db.book.aggregate([
      {
        $unwind: "$chapters",
      },
      {
        $lookup: {
          from: "chapter",
          localField: "chapters",
          foreignField: "_id",
          as: "chapter",
        },
      },
      {
        $match: {
          "chapter.status": "unfinished",
        },
      },
      {
        $group: {
          _id: "$_id",
          title: { $first: "$title" },
        },
      },
    ]);
    

    您可以随时根据需要调整上述查询。

    Example

    【讨论】:

    • 嘿,这回答了你的问题吗?
    【解决方案2】:

    您可以尝试使用aggregate()

    • $lookup有管道,加入章节合集
    • $match 2个条件第一个匹配chatsIds中的chapter_id,第二个状态等于unfinished
    • $match 匹配不等于空数组的章节
    • $project 显示或隐藏必填字段
    db.Book.aggregate([
      {
        "$lookup": {
          from: "Chapter",
          as: "chapters_list",
          let: { chapterIds: "$chapters" },
          pipeline: [
            {
              $match: {
                $expr: {
                  $and: [
                    { $in: ["$_id", "$$chapterIds"] },
                    { $eq: ["$status", "unfinished"] }
                  ]
                }
              }
            }
          ]
        }
      },
      {
        $match: { chapters_list: { $ne: [] } }
      },
      // if you want chapters_list array then remove $project this part
      {
        $project: { chapters: 1, title: 1 }
      }
    ])
    

    Playground

    【讨论】:

    • in $lookup, $match 在管道中仅使用带有 $eq 的索引
    • 我不明白你在问吗?您可以像我们使用外部查找一样正常使用管道。
    • 我是说只有$eq可以在$lookup的管道内使用索引
    • 好的,你知道有没有这方面的参考文档?你怎么知道的?
    • 很高兴我不知道这个,谢谢你的信息。
    猜你喜欢
    • 2013-11-25
    • 2021-05-29
    • 2013-07-05
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多