在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中获得的所有值都作为查询中的参数。

09-25 19:44