![](/img/trans.png)
[英]Mongoose/MongoDB Aggregation - $match $unwind $match not working?
[英]MongoDB/Mongoose aggregation or $or not working as expected?
在HTML中有一些复选框按钮,我想通过AJAX上的API on.click过滤结果。 结果分为3种:upVoted,noVote,downVoted。 根据选中哪个复选框,将向用户显示upVoted,noVote和downVoted文档的组合。
ajax调用API的URL,并在node.js API中通过以下循环运行后,数据正确到达数据库调用,该循环遍历字符串数组[“ upVoted”,“ noVote”,“ downVoted” ](或其任意组合),并将true的布尔值分配给相应的变量:
var upVoted = false;
var noVote = false;
var downVoted = false;
storyFiltering.forEach(storyFiltering);
function storyFiltering(element, index, array) {
if (element == 'upVoted') {upVoted = true}
else if (element == 'noVote') {noVote = true}
else if (element == 'downVoted') {downVoted = true}
}
console.log('upVoted: ' + upVoted + ', noVote: ' + noVote + ', downVoted: ' + downVoted);
然后,这些变量将与每个文档中投票的布尔值匹配。
这是数据库结构(一次投票只有一个布尔值为真,其余为false):
to: ["user1"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 4
to: ["user2"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 2
to: ["user1", "user2"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 1
to: ["user1", "user2"],
voting: {
upVoted: false,
noVote: true,
downVoted: false
},
rank: 5
to: ["user1"],
voting: {
upVoted: false,
noVote: false,
downVoted: true
},
rank: 3
查找(或汇总)的结果将是过滤数据以匹配切换后的投票布尔值的回调,然后按降序对它们进行排序。
切换user1的所有upVoted和noVote文档将返回:
to: ["user1", "user2"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 1
to: ["user1"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 4
to: ["user1", "user2"],
voting: {
upVoted: false,
noVote: true,
downVoted: false
},
rank: 5
..而仅切换user1的upVote文档将返回:
to: ["user1", "user2"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 1
to: ["user1"],
voting: {
upVoted: true,
noVote: false,
downVoted: false
},
rank: 4
..并且以相同的模式,切换用户1的所有upVoted + noVote + downVoted文档将返回包括用户1的所有文档,并按等级(1、3、4、5)排序。 ,切换用户2的所有downVoted文档将返回零文档。
我认为这是您的方法遇到的基本问题。 您想要做的是与用户界面进行交互,该用户界面“选择”您要显示在查询结果中的某些项目。 很好,但是显然您似乎在寻找“一个查询来统治所有对象”,这就是您要解决的问题。
以您的第一个示例为例,对所有“ upvote”和“ novote”文档的查询都是这样显示的。 还说明了现在不进行聚合,但是对于$match
管道的查询也是如此:
db.collection.find({
"to": { "$in": ["user1"] },
"$or": [
{ "voting.upVoted": true },
{ "voting.noVote": true }
]
})
这将返回您的预期结果,因为$or
认为这些条件中的“两个”都可以评估为true
才能满足匹配条件。 如前所述,MongoDB中的所有查询都是隐式的“和”查询,因此这里不需要额外的运算符。
在您的下一个示例中,您实际上只需要满足一个条件即可,因此我们可以删除$or
但稍后将其留作解释。
db.collection.find({
"to": { "$in": ["user1"] },
"$or": [
{ "voting.upVoted": true }
]
})
再次符合您的预期结果,因为这既返回“ user1”存在的位置,又返回“ upVoted”值为true
。
但是,现在到您的界面交互以及如何处理它。 假设您的输入来自界面,如下所示:
{
"to": "user1",
"voting": {
"upVoted": true,
"downVoted": false,
"noVote": true
}
}
这将确认您在用户界面中为查询所做的基本选择。 为了将其“处理”为所需的查询,然后考虑以下JavaScript代码,以将其翻译为您要实现的任何语言。我将假定该结构如图所示位于称为request
的变量中:
var query = {
"to": { "$in": [] },
"$or": []
};
for ( k in request ) {
if ( k == "to" )
query.to["$in"].push( request.to );
if ( k == "voting" ) {
for ( v in request[k] ) {
if ( request[k][v] ) { // if that value is `true`
var obj = {};
obj[ k + "." + v] = true;
query["$or"].push( obj );
}
}
}
}
在该数据上运行代码,结果query
对象如下所示:
{
"to" : {
"$in" : [
"user1"
]
},
"$or" : [
{
"voting.upVoted" : true
},
{
"voting.noVote" : true
}
]
}
这与我们首先发出的查询相同,并根据第二个示例中的显示方式更改了request
的选择:
{
"to": "user1",
"voting": {
"upVoted": true,
"downVoted": false,
"noVote": false
}
}
结果query
对象为:
{
"to" : {
"$in" : [
"user1"
]
},
"$or" : [
{
"voting.upVoted" : true
}
]
}
剩下要做的就是发出使用对象作为参数的查询:
db.collection.find( query )
这样便可以与界面中的数据进行交互。 您进行动态构建,而不是尝试将在response
获得的所有值作为查询中的参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.