MongoDB MapReduce ส่งคืนเมื่อนับเท่านั้น > 1

ฉันมีข้อมูลใน MongoDB โครงสร้างของวัตถุหนึ่งเป็นดังนี้:

{
    "_id" : ObjectId("5395177980a6b1ccf916312c"),
    "institutionId" : "831",
    "currentObject" : {
          "systemIdentifiers" : [
            {
                "value" : "24387",
                "system" : "ABC"
            }]
      }
}

ฉันต้องรู้ว่ามีออบเจ็กต์กี่รายการที่มี institutionId และ systemIdentifiers[0].value เหมือนกัน และต้องการส่งคืนเฉพาะรายการที่ซ้ำกันในลักษณะนั้นเท่านั้น ในการทำเช่นนั้น ฉันจะจัดกลุ่มตามรหัสเหล่านี้และนับจำนวนครั้งที่เกิดขึ้น

ควรส่งคืนออบเจ็กต์ (คู่ของ ID) เมื่อ จำนวน มากกว่า 1

นี่คือโค้ดบางส่วนที่ทำการจัดกลุ่มโดยใช้ MapReduce

var map = function() {
    var key = this.institutionId;
    var val = this.currentObject.systemIdentifiers[0].value;
    emit({"institutionId":key,"workId":val}, {count:1});     
};
var reduce = function(key, values) {
    var count = 0;
    values.forEach(function(v) {
        count += v['count'];
    });
    return {count: count};
}
db.name.mapReduce(map, reduce, {out: "grouped"})
db.grouped.find()

เพื่อให้ได้เฉพาะผู้ที่มีจำนวนมากกว่า 1 ฉันทำได้

db.grouped.aggregate([{$match:{"value.count":{$gt: 1}}}])

ผลลัพธ์ตัวอย่างดังต่อไปนี้

{
    "_id" : {
        "institutionId" : "1004",
        "workId" : "591426"
    },
    "value" : {
        "count" : 2
    }
}

แต่ฉันอยากรู้ว่าถ้าเป็นไปได้ที่จะทำเพียงแค่ทำ MapReduce เป็นคำสั่งเดียวหรือไม่ เช่นการเพิ่ม ตัวสุดท้าย หรือมากกว่านั้น


person Szymon Roziewski    schedule 01.12.2016    source แหล่งที่มา


คำตอบ (2)


แนวทางที่ดีกว่า ง่ายกว่า และมีประสิทธิภาพมากกว่ามากคือการใช้กรอบงานการรวมซึ่งคุณสามารถใช้ตัวดำเนินการเช่น $arrayElemAt เพื่อส่งคืนเอกสารย่อยแรกจากอาร์เรย์ จากนั้นใช้ $group ไปป์ไลน์เพื่อรวมการนับ จากนั้นคุณสามารถวาง $match ไปป์ไลน์เพื่อกรองผลลัพธ์ของคุณตามเกณฑ์ที่กำหนด

ตัวอย่างต่อไปนี้แสดงแนวทางที่เร็วกว่านี้:

db.name.aggregate([
    {
        "$project": {
            "key": "$institutionId",
            "val": {
                "$arrayElemAt": ["$currentObject.systemIdentifiers", 0]
            }
        }
    },
    {
        "$group": {
            "_id": {
                "institutionId": "$key",
                "workId": "$val.value"
            },
            "count": { "$sum": 1 }
        }
    },
    { "$match": { "count": { "$gt": 1 } } }
])
person chridam    schedule 06.12.2016

หากมีเอกสารฉบับเดียวที่มีคีย์ มันจะ ไม่เข้าไปข้างใน ลด ถือว่าลดแล้ว นั่นคือพฤติกรรมของ MongoDB map-reduce:

MongoDB จะไม่เรียกใช้ฟังก์ชันลดสำหรับ คีย์ที่มีค่าเพียงค่าเดียว

การใช้ Finalzie ก็ไม่ได้ช่วยอะไรมากนัก เช่น หากในการสรุปฟังก์ชั่น คุณใช้ if count > 1 then return reducedVal else None คุณจะไม่มี None (แทนที่จะเป็น 1) ในผลลัพธ์

ฉันเกรงว่าการใช้ (หนึ่ง) การลดแผนที่ เอกสารที่มีการนับ 1 จะ เสมอ ในผลลัพธ์ เนื่องจากเอกสารเหล่านั้นถูกไล่ออกจากแผนที่

คุณสามารถใช้ 2 map ลดการดำเนินการแบบลูกโซ่ ในแผนที่ที่สอง คุณจะไม่ปล่อยเอกสารที่มีการนับ ‹ 2 แต่สิ่งเหล่านี้ไม่คิดว่าจะดีกว่าแบบสอบถามเพิ่มเติมตามที่อยู่ในตัวอย่างของคุณ

person sergiuz    schedule 01.12.2016