【问题标题】:Find all documents where a particular field of all elements of a subcollection are included inside a given array in MongoDB / Mongoose查找所有文档,其中子集合的所有元素的特定字段包含在 MongoDB / Mongoose 的给定数组中
【发布时间】:2015-04-15 07:13:38
【问题描述】:

使用 MongoDB 和 Mongoose,例如,我有这个架构:

var componentSchema = mongoose.Schema({
name             : String,
price            : Number
});

var partSchema = mongoose.Schema({
componentId        : { type: Schema.Types.ObjectId, ref: 'Component' },
quantity           : Number
});

var robotSchema = mongoose.Schema({
name             : String,
type             : Number,
parts            : [partSchema]
});

每个机器人都需要构建一组组件。

由于机器人可能需要多个组件的单个副本(例如 10 个螺栓、5 个螺钉、1 个晶体管...),我们在机器人模型中存储了一个 零件 数组,其中每个部分都包含对组件的引用以及一个附加字段,数量。

现在我有兴趣在给定 组件 名称数组(或者,最终给定组件 ID 数组)的情况下查找我可以使用这些类型的组件构建的所有机器人 (请注意,一个组件不包括数量,我只是假设我有无限数量的这些组件),按使用给定数组中大多数组件的那个排序。

Robot A: 2 bolts, 2 transistors 
Robot B: 10 bolts, 2 capacitors, 3 bars of plutonium  
Robot C: 5 bolts, 1 capacitor, 5 transistors

I have [bolts, capacitors, transistors]. 
Query results:  

    Robot C  
    Robot A 

(In this order!)

复杂的 MongoDB 查询甚至可以实现吗?

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    当然。您希望找到机器人文档,对于组件列表中的每个组件,信息中该组件的数量少于机器人文档中列出的数量,并且您的组件列表耗尽了机器人的组件列表。

    // robot docs
    {
        "name" : "My Fun Robot v3",
        "type" : 999,
        "parts" : [
            { "_id" : 0, "quantity" : 2 },
            { "_id" : 1, "quantity" : 5 },
            { "_id" : 2, "quantity" : 1 },
            { "_id" : 3, "quantity" : 7 }
        ]
    },
    {
        "name" : "My Pun Robot v1",
        "type" : 222,
        "parts" : [
            { "_id" : 4, "quantity" : 3 },
            { "_id" : 1, "quantity" : 4 },
            { "_id" : 2, "quantity" : 8 },
            { "_id" : 6, "quantity" : 1 }
        ]
    },
    {
        "name" : "My Sun Robot v876",
        "type" : 9834,
        "parts" : [
            { "_id" : 0, "quantity" : 6 },
            { "_id" : 1, "quantity" : 400 },
            { "_id" : 2, "quantity" : 800 },
            { "_id" : 3, "quantity" : 1000 }
        ]
    },
    {
        "name" : "My Gun Robot v0",
        "type" : 1337,
        "parts" : [
            { "_id" : 0, "quantity" : 1 },
            { "_id" : 1, "quantity" : 1 },
            { "_id" : 2, "quantity" : 1 },
        ]
    }
    

    和组件信息

    \\ component info
    var components = [
        { "_id" : 0, "quantity" : 20 },
        { "_id" : 1, "quantity" : 20 },
        { "_id" : 2, "quantity" : 20 },
        { "_id" : 3, "quantity" : 20 },
        { "_id" : 4, "quantity" : 20 }
    ]
    

    查询的构造:

    // for each component, we either need the component not to be required for the robot, or for the robot's quantity required to be less than the quantity we have
    var query = {}
    var comp_cond = []
    components.forEach(function(comp) {
        comp_cond.push({ "$or" : [{ "parts" : { "$elemMatch" : { "_id" : comp._id, "quantity" : { "$lte" : comp.quantity } } } }, { "parts._id" : { "$ne" : comp._id } } ]})
    })
    query["$and"] = comp_cond
    // we need to make sure that there's no part in `parts` that's not in the components array
    query["parts"] = { "$not" : { "$elemMatch" : { "_id" : { "$nin" : components.map(function(comp) { return comp._id }) } } } }
    

    我不会显示上述示例的实际查询,因为它真的很长。你可以在 mongo shell 中运行代码并查看。

    > db.robots.find(query, { "_id" : 0, "name" : 1 })
    { "name" : "My Fun Robot v3" }
    { "name" : "My Gun Robot v0" }
    

    我相信这是正确的结果。您应该进行更详尽的测试,以确保它能够处理组件列表无法匹配机器人零件列表的所有方式。

    【讨论】:

    • 非常感谢这个伟大的答案,我正在做一些测试,一旦我有一些切实的结果,我会在这里更新。
    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 2016-07-29
    • 2021-02-10
    • 2020-10-02
    • 2018-06-18
    • 2022-01-17
    • 1970-01-01
    • 2020-12-27
    相关资源
    最近更新 更多