2016-12-05 33 views
2

從MySQL來的問題,我想知道,我們如何在MongoDB的多個集合中找到重複內容?在多個MongoDb集合中查找重複內容

讓說,我有兩個(或更多)的集合:

人:

  • _id

貓:

  • _id
  • 暱稱

什麼將是一個有效的解決方案,列出重複的名字。這包括如果名稱僅由2+用戶,僅由2+貓或至少一個用戶和一隻貓使用。我們的結果應該爲此包含針對這些集合(貓和人具有相同的名稱)

預期結果兼具收藏和副本的副本:

重複的值的列表,occurence的數量可能是有趣的,但不是必需的。


問題不在於建議的數據庫模式是否適合在這種情況下,而是關於最好的MongoDB解決方案。

編輯

我重複的描述是不是真的是我的本意是,如果它不是在一個集合存在,但是在另一個集合仍然是一個重複

+0

你正在運行哪個mongod版本? – styvane

+0

這僅僅是爲了知識,並非真正的用例,所以我們假設最後一個,3.4 – DessDess

回答

1

對於兩個集合與MongoDB的3.2可以使用$lookup聚合(它相當於LEFT OUTER JOIN你在MySQL中使用):

db.human.aggregate([ 
    {$group: {_id: "$firstname"}}, 
    {$lookup: { 
      from: "cat", 
      localField: "_id", 
      foreignField: "nickname", 
      as: "cats" 
     } 
    }, 
    {$match:{cats:{$ne:[]}}}, 
    {$project: {catsCount:{$size:"$cats"}}}]) 

階段:

  1. 按姓名分組人類,因爲可能有同名人類
  2. 附加到與組ID相同的暱稱的貓的每組數組(即,人姓名)
  3. 過濾掉沒有任何比賽在貓收集
  4. 項目結果得到的只有名字和匹配的計數的人類

結果會像

[ 
    { _id: "Bob", catsCount: 2 }, 
    { _id: "Alex", catsCount: 1 } 
] 

注意:如果您需要加入多個集合,則可以多次應用$ lookup階段。

+0

@DessDess只記得MongoDB與像MySQL這樣的關係數據庫不同。它提供了很好的可伸縮性,無模式文檔以及將數據嵌入到文檔中的選項(例如用戶地址列表)。但它沒有多文檔交易,這裏加入的主要目的是報告。 –

+0

是的,我確實認爲這種情況不應該發生在一個良好的設計模式中,它只是一個開放的問題。關於你的答案,我發現我的問題沒有很好地解釋爲此感到遺憾,如果我們也希望重複的用戶被認爲是重複的,該怎麼辦?我相應地更新了我的問題 – DessDess

+0

好的,當然你可以結合這個結果和2個查詢來從每個集合中獲取重複,所以你的答案仍然很好,但是有沒有辦法在單個查詢中完成? – DessDess

0

一個解決方案,我被複制發現:

  1. Combine data in one collection
  2. Find duplicates in the collection
  3. And export it in a table

代碼:

mapHuman = function() { 
    var values = { 
     name: this.firstname 
    }; 
    emit(this._id, values); 
}; 
mapCat = function() { 
    var values = { 
     name: this.name 
    }; 
    emit(this._id, values); 
}; 

reduce = function(k, values) { 
    var result = {names: []}; 
    values.forEach(function(value) { 
     result.names.push(value.slug); 
    }); 
    return result; 
}; 

db.human.mapReduce(mapUsers, reduce, {"out": {"reduce": "name"}}); 
db.cat.mapReduce(mapUsers, reduce, {"out": {"reduce": "name"}}); 

db.name.aggregate(
    {"$group" : { "_id": "$value.name", "count": { "$sum": 1 } } }, 
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0}}, 
    {"$out": "duplicate"} 
) 

db.duplicate.find()