簡體   English   中英

如何通過將數組元素與 MongoDB 中的 MapReduce 匹配來對文檔進行分組?

[英]How to group documents by matching array elements with MapReduce in MongoDB?

我有一個包含字符串數組的列的數據庫。 示例表:

name | words                          | ...
Ash  | ["Apple", "Pear", "Plum"]      | ...
Joe  | ["Walnut", "Peanut"]           | ...
Max  | ["Pineapple", "Apple", "Plum"] | ...

現在我想將此表與給定的單詞數組進行匹配,並按匹配率對文檔進行分組。

具有預期結果的示例輸入:

// matched for input = ["Walnut", "Peanut", "Apple"]
{
  "1.00": [{name:"Joe", match:"1.00"}],
  "0.33": [{name:"Ash", match:"0.33"}, {name:"Max", match:"0.33"}]
}

我正在使用以下map函數以匹配率作為關鍵來發出文檔:

function map() {
    var matches = 0.0;
    for(var i in input) 
      if(this.words.indexOf(input[i]) !== -1) matches+=1;
    matches /= input.length;
    var key = ""+matches.toFixed(2);
    emit(key, {name: this.name, match: key});
}

現在缺少的是匹配的reduce函數,用於將發出的 KV 對組合到結果對象中。

我試過這樣:

function reduce(key, value) {
    var res = {};
    res[key] = values;
    return res;
}

但是我對規范有問題

MongoDB 可以為同一個鍵多次調用 reduce 函數。 在這種情況下,該鍵的reduce 函數的先前輸出將成為該鍵的下一個reduce 函數調用的輸入值之一。

...導致嵌套的結果對象。 按匹配對文檔進行分組的正確方法是什么?

為同一個鍵多次調用 reduce 函數。

這就是冪等性,reduce 函數必須尊重這一點。

但是,為了簡單起見,您只需要確保地圖輸出的格式與reduce 的格式相同。

對於你的情況,這樣的事情會起作用:

db.col.insert({"name": "Ash", "words": ["Apple", "Pear", "Plum"]})
db.col.insert({"name": "Joe", "words": ["Walnut", "Peanut"]})
db.col.insert({"name": "Max", "words": ["Pineapple", "Apple", "Plum"]})

function map() {

    input = ["Walnut", "Peanut", "Apple"]

    var matches = 0.0;
    for(var i in input) 
      if(this.words.indexOf(input[i]) !== -1) matches+=1;
    matches /= input.length;
    var key = ""+matches.toFixed(2);

    emit(key, {users: [{name: this.name, match: key}]});
}

function reduce(key, value) {

    ret = value[0]

    for(var i=1; i<value.length; i++){
        ret.users = ret.users.concat(value[i].users)
    }

    return ret

}

db.col.mapReduce(map, reduce, {"out": {inline:1}})

輸出:

{
    "results" : [
        {
            "_id" : "0.33",
            "value" : {
                "users" : [
                    {
                        "name" : "Ash",
                        "match" : "0.33"
                    },
                    {
                        "name" : "Max",
                        "match" : "0.33"
                    }
                ]
            }
        },
        {
            "_id" : "0.67",
            "value" : {
                "users" : [
                    {
                        "name" : "Joe",
                        "match" : "0.67"
                    }
                ]
            }
        }
    ],
    "timeMillis" : 22,
    "counts" : {
        "input" : 3,
        "emit" : 3,
        "reduce" : 1,
        "output" : 2
    },
    "ok" : 1
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM