簡體   English   中英

使用Map Reduce旋轉數據時遇到問題

[英]Trouble Pivoting data with Map Reduce

我在使用map reduce旋轉數據集時遇到麻煩。 我一直在使用MongoDB食譜尋求幫助,但是卻遇到了一些奇怪的錯誤。 我想采用以下集合並對其進行透視,以便每個用戶都有所有評論評分的列表。

我的收藏看起來像這樣:

{
  'type': 'review',
  'business_id': (encrypted business id),
  'user_id': (encrypted user id),
  'stars': (star rating),
  'text': (review text),
}

地圖函數(包裝在Python中):

map = Code(""""
function(){
key = {user : this.user_id};
value = {ratings: [this.business_id, this.stars]};

emit(key, value);
}
""")

map函數應返回與鍵關聯的值的數組... Reduce函數(包裝在Python中):

reduce = Code("""
function(key, values){
var result = { value: [] };
temp = [];

for (var i = 0; i < values.length; i++){
temp.push(values[i].ratings);
}
result.value = temp;
return result;
}
""")

然而,返回的結果不是總少了一個等級。 實際上,某些用戶沒有返回任何值,這是不可能發生的。 一些條目如下所示:

{u'_id': {u'user: u'zwZytzNIayFoQVEG8Xcvxw'}, u'value': [None, [u'e9nN4XxjdHj4qtKCOPQ_vg', 3.0], None, [...]...]

我無法查明是什么原因導致了這個問題。 如果有3條評論,則它們在文檔中都具有業務ID和等級。 另外,由於某種原因,在我的循環條件中使用'values.length + 1'會破壞values [i]。

編輯1

我已經接受了reduce本身被多次調用的事實,因此下面是我的新reducer。 這將返回[業務,等級,業務,等級]數組。 知道如何輸出[業務,評級]數組而不是一個巨型數組嗎?

function(key, value){
var result = { ratings:[] };
var temp = [];
values.forEach(function(value){
    value.ratings.forEach(function(rating){
        if(temp.indexof(rating) == -1){
            temp.push(rating);
        }
    });
});

result. rartings = temp;
return result;
}

這是一個測試示例:

1)添加一些示例數據:

db.test.drop();
db.test.insert(
  [{
    'type': 'review',
    'business_id': 1,
    'user_id': 1,
    'stars': 1,
  },
  {
    'type': 'review',
    'business_id': 2,
    'user_id': 1,
    'stars': 2,
  },
  {
    'type': 'review',
    'business_id': 2,
    'user_id': 2,
    'stars': 3,
  }]
);

2)地圖功能

var map = function() {
  emit(this.user_id, [[this.business_id, this.stars]]);
};

在這里,我們設置結果,就像我們希望它們在過程結束時一樣。 為什么? 因為如果用戶只進行過一次審核(我們所依據的鍵),那么結果將不會經過簡化階段。

3)縮小功能

var reduce = function(key, values) {
  var result = { ratings: [] };
  values.forEach(function(value){
    result.ratings.push(value[0]);
  });

  return result;
};

在這里,我們收集了所有值,並記住我們將它們嵌套在map方法中,因此我們只需為每組結果選擇第一個值即可。

4)運行地圖reduce:

db.test.mapReduce(map, reduce, {finalize: final, out: { inline: 1 }});

替代方法-使用聚合框架

db.test.aggregate({
  $group: {
    _id: "$user_id", 
    ratings: {$addToSet: {business_id: "$business_id", stars: "$stars"}}
  }
});

暫無
暫無

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

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