查找文档的数组计数

时间:2017-05-06 14:12:17

标签: php mongodb

我有2个收藏:单词和短语 每个word文档都有一个短语id的数组。每个短语都可以是活动的或非活动的。

例如:

单词:
{“word”=> “你好”,短语=> [1,2]}
{{word“=> “table”,短语=> [2]}

短语:
{{id“=> 1,“短语”=> “你好世界!”,“主动”=> 1}
{{id“=> 2,“短语”=> “你好,我已经买了新桌子”,“主动”=> 0}

我需要为每个单词计算活动短语。

在php中我这样做:
 1.得到所有的词  2.对于每个单词,获取具有条件的活动短语的计数['active'=> 1]

问题:如何在一个请求中获得包含活动短语的单词?我尝试使用MapReduce,但我需要为每个单词发出请求以获取活动短语的计数。

UPD: 在我的测试集中,有92000个短语和23000个单词。

我已经测试了两个变体:每个单词的php循环,其中我得到短语计数和mongo中的aggreagation函数。

但是由于phrase_data,我改变了聚合管道以表达以下内容。它是数组,所以我不能使用$ match。我在$ lookup之后使用$ unwind。

[ '$unwind'  =>  '$5'],
    [
        '$lookup' =>  [
        'from' =>  'phrases_926ee3bc9fa72b029e028ec90e282072ea0721d1',
            'localField' =>  '5',
            'foreignField' =>  '0',
            'as' =>  'phrases_data'
        ]
    ],
    [ '$unwind'  =>  '$phrases_data'],
    [ '$match'  =>  [ 'phrases_data.3'  =>  77] ], //phrases_data.3 => 77 it is similar to phrases_data.active => 1
    [ '$group'  =>  
        [
            '_id'  =>  ['word'  =>  '$1', 'id'  =>  '$0'],
            'active_count'  =>  [ '$sum'  =>  1]
        ]
    ],
    [ '$match'  =>  [ 'active_count'  =>  ['$gt' => 0]] ],
    [ '$sort'  =>
        [
            'active_count'  => -1
        ]
    ]


问题是$ group命令占用了80%的处理时间。而且它比php循环要慢得多。以下是我的测试收集结果:

1. Php loop (get words-> get phrases count for each word): 10 seconds
2. Aggregation function : 20 seconds

1 个答案:

答案 0 :(得分:0)

db.words.aggregate([
    { "$unwind" : "$phrases"},
    {
        "$lookup": {
            "from": "phrases",
            "localField": "phrases",
            "foreignField": "id",
            "as": "phrases_data"
        }
    },
    { "$match" : { "phrases_data.active" : 1} },
    { "$group" : {
        "_id" : "$word",
        "active_count" : { $sum : 1 }
        }
    }
]);

您可以使用以上聚合管道:

  1. 将单词集合文档中的短语数组作为单独的文档展开
  2. 使用unwinded phrase
  3. 在短语集合中进行查找(加入)
  4. 使用$ match
  5. 过滤短语并检查是否有效
  6. 最后使用$ sum:1
  7. 按字和计数对短语进行分组