javascript - Meteor 比较集合中的嵌入数组

标签 javascript node.js mongodb meteor mongodb-query

我有三个集合:

UserCollectionDepartmentCollectionQuestionsCollection

QuestionsCollection 是一个可配置的问题列表。

每个用户和部门都回答从 QuestionsCollection 生成的调查,因此每个用户和部门都有一个嵌入的 questionAnswer 对象数组,每个对象都有一个 questionidanswer 属性。

来自 UserCollection 的示例用户文档如下:

        {
            id:SoEtnNvN8B3QYcd3N,
            questionAnswers:[
            {
               questionId: 1, 
               answer: "melbourne"
            }, 
            {
               questionId: 2,
               answer: "10"}]
            }
        }

一个部门将具有相同的嵌入数组,但可以包含更多或更少的 QuestionAnswer 对象。当然有不同或相同的答案。

问题:

我想做的是能够获取单个用户问题答案数组作为搜索条件,并查看有多少部门与这些问题答案匹配。

匹配将在两个属性上匹配,并且用户必须回答部门已回答的相同问题才能匹配,例如

  • 如果该部门回答的问题多于用户的问题,则该部门自动不再是 匹配。
  • 如果用户和部门回答了相同数量的问题,则所有问题答案值都应匹配。
  • 如果用户回答的问题多于某个部门的问题,则所有部门的问题答案都必须包含在用户的问题答案中。

答案将是完全匹配的,尽管我可能在某些时候需要一种进行范围搜索的机制。

我已经考虑过使用用户 QuestionAnswers 数组构建查询并使用 $elemMatch 在 DepartmentCollection 上进行搜索,但我不确定如何实现这一点。任何帮助或指导将不胜感激。

最佳答案

这是您必须根据您正在处理的当前用户的数据在代码中“构建”查询的情况之一。

为了根据您的条件进行匹配,必须进行查询以匹配多个条件的逻辑。用户数据的数组形式很有用,但并不完全适合实际所需的查询部分。因此它需要一些转换,并且根据示例数据,您将形成如下形式:

// Actually found by querying for the required user
var user =  {
   "id": "SoEtnNvN8B3QYcd3N",
   "questionAnswers":[
       {
           "questionId": 1, 
           "answer": "melbourne"
        }, 
        {
           "questionId": 2,
           "answer": "10"
        }
   ]
};

// Basic query
var query = {
    "$or": [
        { "$and": [ ] },
        { 
            "questionAnswers": { "$size": 1 },
            "$or": []
        }
    ]
};

// add the elements
user.questionAnswers.forEach(function(answer) {
    query.$or[0].$and.push({ "questionAnswers": { "$elemMatch" : answer }});
    query.$or[1].$or.push({"questionAnswers": { "$elemMatch":  answer }});
});


Department.find(query);

根据“用户”的数据,查询将按如下方式构造:

{
    "$or" : [
        {
            "$and" : [
                {
                    "questionAnswers" : { "$elemMatch" : {
                        "questionId" : 1,
                        "answer" : "melbourne"
                    }}
                },
                {
                    "questionAnswers" : { "$elemMatch" : {
                        "questionId" : 2,
                        "answer" : "10"
                    }}
                }
            ]
        },
        {
            "questionAnswers" : {
                "$size" : 1
            },
            "$or" : [
                {
                    "questionAnswers" : { "$elemMatch" : {
                        "questionId" : 1,
                        "answer" : "melbourne"
                    }}
                },
                {
                    "questionAnswers" : { "$eleMatch" : {
                        "questionId" : 2,
                        "answer" : "10"
                    }}
                }
            ]
        }
    ]
}

对于每个条件,整个语句都由 $or 包裹。在第一个文档中,文档必须“全部匹配”$and 语句内设置的条件,该语句是查询条件数组。

在顶部的第二个元素中,$or本质上是一个$and条件(以自然隐式方式,因为键不会冲突),它首先根据您的规则考虑数组的$size,因此只有具有单个元素的数组。配对条件位于另一个 $or 内,以查看该单个元素是否与从用户提供的“questionAnswers”派生的“任何”条件匹配。因此,如果单个元素与任何一个用户元素匹配,那么它就是一个匹配。

最后,$elemMatch 为您的设计提供了一定的灵 active ,因为目标数组文档可能包含比源数据中更多的属性,甚至属性键的顺序不同。如果没有该运算符,数组的子文档将需要与源“完全匹配”。

关于javascript - Meteor 比较集合中的嵌入数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29022961/

相关文章:

node.js - 保存 Sequelize 记录/在另一个模型中引用它

node.js - Mongo 上的计数(字段)

java - 如何使用 Java 将带有一些数据的图像存储在 MongoDB 中

javascript - JQuery empty() 方法如何工作?

javascript - 共享后端和前端输入验证或模块

javascript - 替换字符串中的管道

javascript - 如何填充嵌套在 Mongoose 对象数组中的文档?

javascript - 在它们之间切换时,jQuery 文本显示在事件文本下方

c++ - 我应该如何用 NAN 1.x 中的数字代码抛出错误?

java - 获取 "err": "E11000 duplicate key error when inserting into mongo using the Java driver