【问题标题】:How can I write results of aggregation operation in pymongo as one document in another collection如何在 pymongo 中将聚合操作的结果写为另一个集合中的一个文档
【发布时间】:2019-09-01 04:39:41
【问题描述】:

好吧,我想创建某种 MapReduce 算法来为文本文档创建反向索引。 在映射部分,我做了这样的事情

letters = ['a']
regx = re.compile("^("+"|".join(letters)+')')
selectedWords = directIndex.aggregate([
    { "$match": { "words.word": regx } },
    { "$unwind": "$words" },
    { "$match": { "words.word": regx } },
    { "$group": { "_id": { "word":"$words.word", "count":"$words.count", 'document' : '$document' } } }])

好吧,在这里,我按首字母选择所有与之相关的单词和信息。在此之后,我将此信息写入另一个集合:

myinvcol.insert_one({'letter':str(''.join(letters)),'words':selectedWords })

在下一步中,我正在读取每个插入的文档并执行缩减操作 dict('wordName':{documents:[document1:count1, document2:count2, etc], 'wordName2:{documents:[...] }') 并对这个字典做一些额外的操作

现在,有趣的部分)): 是否可以在 MongoDB 服务器上完全执行第一步(地图部分),也就是聚合?换句话说,我知道有 '$out' 运算符:

letters = ['a']
regx = re.compile("^("+"|".join(letters)+')')
selectedWords = directIndex.aggregate([
    { "$match": { "words.word": regx } },
    { "$unwind": "$words" },
    { "$match": { "words.word": regx } },
    { "$group": { "_id": { "word":"$words.word", "count":"$words.count", 'document' : '$document' } } }
    { "$out" : 'InverseIndex'}])

它允许我将聚合结果写入另一个集合,但它不能做我想要的:而不是插入一个文档:

{'letter':str(''.join(letters)),'words':selectedWords }, 

我有很多插入

{ "_id": { "word":"$words.word", "count":"$words.count", 'document' : '$document' } }. 

那么,最后,有没有一种方法可以在聚合中创建一个文档,在 $out 语句之前将其所有结果合并到一个数组中?

【问题讨论】:

    标签: python-3.x mongodb mapreduce aggregate pymongo


    【解决方案1】:

    嗯,经过一番研究,发现这可能是一个解决方案>

    regx = re.compile("^("+"|".join('ab')+')')
    myinvcol.insertMany(mydb.runCommand(
    {
     'aggregate': "DirectIndex",
        'pipeline': 
        [
        { "$match": { "words.word": regx } },
        { "$unwind": "$words" },
        { "$match": { "words.word": regx } },
        { "$group": { "_id": { "word":"$words.word", "count":"$words.count", 'document' : '$document' } } },
        { "$group": {
            "_id": {'$substr':[''.join('ab'),0,len(''.join('ab'))]},
            "words": {
                "$push": {
                    "word": "$_id.word",
                    "count":"$_id.count",
                    'document' : '$_id.document'
                }
            }
        }},
        {'$out':"InverseIndex"}
    ]}).result)
    

    (在这里找到mongoDB: how to reverse $unwind) 但是在这里,mongo 很糟糕。 out 参数覆盖集合的内容。所以如果我不止一次调用这个,之前的结果就会消失。 正如我在这里看到的:How do I append Mongo DB aggregation results to an existing collection?,Mongo 4.2 将有 $out 的特殊参数,称为模式:“replaceDocuments”。这将允许您将新内容附加到您的收藏中。但就目前而言,死路一条。

    好吧,我尝试通过 mongo 内置的 map_reduce 函数调用来做到这一点:

    mape = Code("function () {"
        "var docName =this.document;"
                       "this.words.forEach(function(z) {"
                       "z['document'] = docName;"
                       "var temp = z.word;"
                       "delete z.word;"
        "    emit(temp, {'documents':[z]});"
        "  });"
        "}")
    reduce = Code("function (key, values) {"
               "  var total = [];"
               "  for (var i = 0; i < values.length; i++) {"
               "for (var j=0;j<values[i]['documents'].length;j++){"
                    "total.push({'document':values[i]['documents'][j]['document'], 'count':values[i]['documents'][j]['count'], 'tf':values[i]['documents'][j]['tf']});"
               "  }}"
               "  return {'documents': total};"
           "}")
    finalizeFunction = Code("function (key, reducedVal) {"
            "if('documents' in reducedVal){"
                "var normVal = Math.log((1+"+str(nrDocs)+")/(1+1+reducedVal.documents.length));"
                "reducedVal['idf']=normVal;"
                "return reducedVal;} else{ return null;}"
            "};")
    result = mydb.DirectIndex.map_reduce(mape, reduce, {'merge':"InverseIndex"},finalize=finalizeFunction)
    

    这以某种方式满足了我的需求。缺点是速度。与手工实现的 MapReduce 相比(通过 dict 进行聚合+映射,其中 key 是 word),差异很大。无论如何,如果有人遇到这个问题,我只知道这两种方法来解决它。

    【讨论】:

      猜你喜欢
      • 2018-10-19
      • 1970-01-01
      • 2015-10-23
      • 2014-01-25
      • 2016-11-26
      • 2019-09-11
      • 2023-03-17
      • 1970-01-01
      • 2017-07-12
      相关资源
      最近更新 更多