node.js - MongoDB/Mongoose 聚合或 $or 未按预期工作?

标签 node.js mongodb mongoose aggregation-framework

在 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/

相关文章:

Node.js - 在 excel 中获取上标和下标

javascript - 通过node.js运行静态文件时,如何调用node.js文档中定义的函数?

javascript - 在 node.js 中使用 emit 函数

node.js - Mongoose 有条件地填充子文档

javascript - object.save() 不是函数错误

javascript - Node JS : Unexpected token ILLEGAL

python - 蒙戈 : combining AND and OR

mongodb - 仅返回嵌套数组中匹配的子文档元素

ruby - unicorn 服务器 mongodb 和 sinatra

mongodb - 如何在mongodb数组中获取匹配的文档?