Meteor和Mongo AND标签过滤器扭曲

时间:2014-11-03 01:24:21

标签: javascript mongodb meteor mongodb-query

Meteor应用程序,我有一个带有标签字段的mongo集合。

[{name: "ABC", tags: {"@Movie", "#free", "!R"}},
 {name: "DEF", tags: {"@Movie", "!PG"}},
 {name: "GHI", tags: {"@Sports", "#free"}}]

在我的用户界面上,根据标记名称的第一个字母,有三组复选框即时填充。

filter group 1: [ ]Movie [ ] Sports
filter group 2: [ ]free
filter group 3: [ ]PG [ ]R

过滤器逻辑如下:

  • 如果过滤器组为空,则不要按该过滤器组进行过滤
  • 如果选中过滤器组中的任何复选框,则应用该过滤器
  • $并且应该应用于过滤器组之间(如果检查了电影和R,则只应选择具有名为“!Movie”和“#free”的标签的文档

我正在努力构建遵循上述逻辑的mongo标准参数。我的代码目前看起来像意大利面,有很多嵌套ifs(伪代码)

如果(filter_group1为空)则if(filter_group2为空)然后mongo_criteria = {_id:$ in:$(“input:checked”,“。filtergroup1”)。map(function(){return this.value} )}

这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

首先,我确定你的意思是"标签"实际上是一个数组,否则结构将无效:

{ "name": "ABC", "tags": ["@Movie", "#free", "!R"]},
{ "name": "DEF", "tags": ["@Movie", "!PG"]},
{ "name": "GHI", "tags": ["@Sports", "#free"]}

存储"标签"这是一个新颖的想法。这样的数据,但似乎构建查询的程序逻辑似乎需要知道至少有三个"三个"需要在$and组合中考虑的可能条件。

在最简单的形式中,您只允许每个过滤器组进行一次选择,然后您可以通过$all运算符来解决此问题。只是简单的MongoDB shell表示法简洁:

db.collection.find({ "tags": { "$all": [ "@Movie", "!R" ] } })

问题在于,如果你想在一个组上进行多次选择,例如说评级,那么这将无法得到结果:

db.collection.find({ "tags": { "$all": [ "@Movie", "!R", "!PG" ] } })

实际上没有任何项目包含这些评级值,因此这将无效。所以你宁愿这样做:

db.collection.find({ "$and": [
    { "tags": { "$in": [ "@Movie" ] } },
    { "tags": { "$in": [ "!R", "!PG" ] } }
])

这样可以正确地匹配所有电影的评分标签为" R"和" PG"。将此扩展为另一个组基本上是将另一个数组项推送到$and表达式:

db.collection.find({ "$and": [
    { "tags": { "$in": [ "@Movie" ] } },
    { "tags": { "$in": [ "!R", "!PG" ] } },
    { "tags": { "$in": [ "#free" ] }
])

仅获取包含其中每种"类型的文档"过滤器的匹配值,所以" PG"电影不是免费的"体育"通过不添加选择来过滤掉。

构建查询的基础是使用每个过滤器组中$in的一组选择选项。当然,当您的过滤器组中存在选择时,您只会附加到$and数组。

首先从这样的基础$and开始:

var query = { "$and":[{}] };

然后将每个过滤器组中的每个已检查选项添加到其中:

var inner = { "tags": { "$in": [] } };
inner.tags["$in"].push( item );

然后附加到基本查询:

query["$and"].push( inner );

冲洗并重复每个项目。这是完全有效的,因为基本查询将只选择未过滤的所有内容,这也是有效的,无需构建其他逻辑:

db.collection.find({ "$and": [
    { },
    { "tags": { "$in": [ "@Movie" ] } },
    { "tags": { "$in": [ "!R", "!PG" ] } },
    { "tags": { "$in": [ "#free" ] }
])

因此,当MongoDB理解它时,它真正归结为查询的构建。这实际上只是构建数据结构时的简单JavaScript数组操作。所有MongoDB查询都是。