4

比方说,我有一个蒙戈集合类似以下内容:查找字符串中的领域最常用的词在整个集合

[ 
    { "foo": "bar baz boo" }, 
    { "foo": "bar baz" }, 
    { "foo": "boo baz" } 
] 

是否有可能以确定哪些词最常出现的foo领域内(最好与计数)?

举例来说,我很乐意设置类似的结果:

[ 
    { "baz" : 3 }, 
    { "boo" : 2 }, 
    { "bar" : 2 } 
] 

回答

5

有最近关闭的JIRA issue$split运营商在聚合框架的$project阶段使用。
由于在地方,你可以创建这样

db.yourColl.aggregate([ 
    { 
     $project: { 
      words: { $split: ["$foo", " "] } 
     } 
    }, 
    { 
     $unwind: { 
      path: "$words" 
     } 
    }, 
    { 
     $group: { 
      _id: "$words", 
      count: { $sum: 1 } 
     } 
    } 
]) 

结果的管道看起来像这样

/* 1 */ 
{ 
    "_id" : "baz", 
    "count" : 3.0 
} 

/* 2 */ 
{ 
    "_id" : "boo", 
    "count" : 2.0 
} 

/* 3 */ 
{ 
    "_id" : "bar", 
    "count" : 2.0 
} 
+0

这看起来非常完美,谢谢。我会尽快将其付诸实施,并按照接受按钮按预期工作。 – user1381745

+0

刚刚使用3.3.10版本进行了测试并正常工作:) – DAXaholic

+0

@DAXholic我该如何处理相同的问题,但它是包含其他分隔符(如逗号)的文章?谢谢 – galgo

0

使用$split运营商分割你的字符串中的MongoDB 3.4做到这一点的最佳途径如here所提到的子串的数组,并且因为我们需要在管线中向下排列数组,所以我们需要使用$facet运算符在子管道中执行此操作以获得最大效率。

db.collection.aggregate([ 
    { "$facet": { 
     "results": [ 
      { "$project": { 
       "values": { "$split": [ "$foo", " " ] } 
      }}, 
      { "$unwind": "$values" }, 
      { "$group": { 
       "_id": "$values", 
       "count": { "$sum": 1 } 
      }} 
     ] 
    }} 
]) 

其产生:

{ 
    "results" : [ 
     { 
      "_id" : "boo", 
      "count" : 2 
     }, 
     { 
      "_id" : "baz", 
      "count" : 3 
     }, 
     { 
      "_id" : "bar", 
      "count" : 2 
     } 
    ] 
} 

从MongoDB的3.2向后,要做到这一点的唯一方法是使用mapReduce

var reduceFunction = function(key, value) { 
    var results = {}; 
    for (var items of Array.concat(value)) { 
     for (var item of items) { 
      results[item] = results[item] ? results[item] + 1 : 1; 
     } 
    }; 
    return results; 
} 

db.collection.mapReduce(
    function() { emit(null, this.foo.split(" ")); }, 
    reduceFunction, 
    { "out": { "inline": 1 } } 
) 

返回:

{ 
    "results" : [ 
     { 
      "_id" : null, 
      "value" : { 
       "bar" : 2, 
       "baz" : 3, 
       "boo" : 2 
      } 
     } 
    ], 
    "timeMillis" : 30, 
    "counts" : { 
     "input" : 3, 
     "emit" : 3, 
     "reduce" : 1, 
     "output" : 1 
    }, 
    "ok" : 1 
} 

你应该考虑使用在一个.forEach()方法减少功能,如果您的MongoDB的版本不支持的for...of声明。

相关问题