我有三个集合:
UserCollection、DepartmentCollection 和 QuestionsCollection
QuestionsCollection 是一个可配置的问题列表。
每个用户和部门都回答从 QuestionsCollection 生成的调查,因此每个用户和部门都有一个嵌入的 questionAnswer 对象数组,每个对象都有一个 questionid 和 answer 属性。
来自 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/