Node.js 查找MongoDB/Mongoose中给定数组中包含子集合所有元素的特定字段的所有文档

Node.js 查找MongoDB/Mongoose中给定数组中包含子集合所有元素的特定字段的所有文档,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,使用MongoDB和Mongoose,比如说,我有以下模式: var componentSchema = mongoose.Schema({ name : String, price : Number }); var partSchema = mongoose.Schema({ componentId : { type: Schema.Types.ObjectId, ref: 'Component' }, quantity

使用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个晶体管…),因此我们在机器人模型中存储了一组零件,其中每个零件都包含对一个组件的引用以及一个额外的字段“数量”

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

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查询,它甚至是可能的吗?

当然。您希望查找robot文档,以便对于组件列表中的每个组件,信息中该组件的数量小于robot文档中列出的数量,并且组件列表将耗尽robot的组件列表

// 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" }

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

非常感谢您的回答,我正在进行一些测试,一旦有具体结果,我将在这里更新。