在 html 中有一些复选框按钮,我想通过 AJAX 通过 API on.click 过滤结果。结果有 3 种:upVoted、noVote、downVoted。根据选中哪个复选框,用户将看到 upVoted、noVote 和 downVoted 文档的组合。
ajax 调用 API 的 URL,在 Node.js API 中运行以下循环后,数据正确到达数据库调用,该循环遍历字符串数组 ["upVoted"、"noVote"、"downVoted"](或其任意组合),并将 bool 值 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);
然后,这些变量与每个文档中投票的 bool 值相匹配。
这是数据库结构(投票时只有一个 bool 值一次为真,其余为假):
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
查找(或聚合)的结果将是过滤后的数据回调,以匹配切换的投票 bool 值......然后按“排名”降序对它们进行排序。
切换 user1 的所有 upVote 和 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 的所有已投票 + 否投票 + 否决文档将返回包括用户 1 的所有文档,按排名 (1, 3, 4, 5) 排序。..相反,切换用户 2 的所有否决文档将返回零个文档。
最佳答案
据我所知,这是您的方法的基本问题。您想要做的是与用户界面进行交互,该用户界面“选择”您想要在查询结果中显示的某些项目。这一切都很好,但显然您似乎正在寻找“一个查询来统治所有”,而这就是您遇到困难的地方。
以您的第一个示例为例,您对所有“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 代码,将其翻译为您想要实现的任何语言。我只是假设所示的结构位于名为 的变量中请求
:
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
}
}
生成的查询
对象是:
{
"to" : {
"$in" : [
"user1"
]
},
"$or" : [
{
"voting.upVoted" : true
}
]
}
剩下要做的就是发出使用该对象作为参数的查询:
db.collection.find( query )
这就是您与界面中的数据进行交互的方式。您可以动态构建,而不是尝试将在响应
中获得的所有值作为查询中的参数抛出。
关于node.js - MongoDB/Mongoose 聚合或 $or 未按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24420880/