it-swarm.com.de

MongoDB: Kombinieren Sie Daten aus mehreren Sammlungen in einem ... wie?

Wie kann ich (in MongoDB) Daten aus mehreren Sammlungen zu einer Sammlung zusammenfassen?

Kann ich map-reduction verwenden und wenn ja, wie?

Ich würde mich sehr über ein Beispiel freuen, da ich ein Anfänger bin.

209
user697697

Obwohl dies nicht in Echtzeit möglich ist, können Sie die Kartenreduzierung mehrmals ausführen, um Daten zusammenzuführen, indem Sie die Option "Reduzieren" in MongoDB 1.8+ map/reduction verwenden (siehe http: // www. mongodb.org/display/DOCS/MapReduce#MapReduce-Outputoptions ). In beiden Auflistungen muss ein Schlüssel vorhanden sein, den Sie als _id verwenden können.

Angenommen, Sie haben eine users-Auflistung und eine comments-Auflistung und möchten eine neue Auflistung mit demografischen Benutzerinformationen für jeden Kommentar erstellen.

Angenommen, die Sammlung users enthält die folgenden Felder:

  • _Ich würde
  • vorname
  • nachname
  • land
  • geschlecht
  • alter

Und dann hat die Sammlung comments die folgenden Felder:

  • _Ich würde
  • benutzeridentifikation
  • kommentar
  • erstellt

Sie würden diese Karte machen/reduzieren:

var mapUsers, mapComments, reduce;
db.users_comments.remove();

// setup sample data - wouldn't actually use this in production
db.users.remove();
db.comments.remove();
db.users.save({firstName:"Rich",lastName:"S",gender:"M",country:"CA",age:"18"});
db.users.save({firstName:"Rob",lastName:"M",gender:"M",country:"US",age:"25"});
db.users.save({firstName:"Sarah",lastName:"T",gender:"F",country:"US",age:"13"});
var users = db.users.find();
db.comments.save({userId: users[0]._id, "comment": "Hey, what's up?", created: new ISODate()});
db.comments.save({userId: users[1]._id, "comment": "Not much", created: new ISODate()});
db.comments.save({userId: users[0]._id, "comment": "Cool", created: new ISODate()});
// end sample data setup

mapUsers = function() {
    var values = {
        country: this.country,
        gender: this.gender,
        age: this.age
    };
    emit(this._id, values);
};
mapComments = function() {
    var values = {
        commentId: this._id,
        comment: this.comment,
        created: this.created
    };
    emit(this.userId, values);
};
reduce = function(k, values) {
    var result = {}, commentFields = {
        "commentId": '', 
        "comment": '',
        "created": ''
    };
    values.forEach(function(value) {
        var field;
        if ("comment" in value) {
            if (!("comments" in result)) {
                result.comments = [];
            }
            result.comments.Push(value);
        } else if ("comments" in value) {
            if (!("comments" in result)) {
                result.comments = [];
            }
            result.comments.Push.apply(result.comments, value.comments);
        }
        for (field in value) {
            if (value.hasOwnProperty(field) && !(field in commentFields)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.users.mapReduce(mapUsers, reduce, {"out": {"reduce": "users_comments"}});
db.comments.mapReduce(mapComments, reduce, {"out": {"reduce": "users_comments"}});
db.users_comments.find().pretty(); // see the resulting collection

Zu diesem Zeitpunkt haben Sie eine neue Sammlung mit dem Namen users_comments, Die die zusammengeführten Daten enthält, und die Sie jetzt verwenden können. Diese reduzierten Sammlungen haben alle den Schlüssel _id, Den Sie in Ihren Kartenfunktionen ausgegeben haben, und dann sind alle Werte ein Unterobjekt innerhalb des Schlüssels value - die Werte liegen nicht bei die oberste Ebene dieser reduzierten Dokumente.

Dies ist ein etwas einfaches Beispiel. Sie können dies mit mehr Sammlungen wiederholen, so oft Sie möchten, um die reduzierte Sammlung weiter aufzubauen. Sie können dabei auch Zusammenfassungen und Aggregationen von Daten vornehmen. Wahrscheinlich würden Sie mehr als eine Reduktionsfunktion definieren, da die Logik zum Aggregieren und Beibehalten vorhandener Felder komplexer wird.

Sie werden auch feststellen, dass jetzt für jeden Benutzer ein Dokument mit allen Kommentaren dieses Benutzers in einem Array vorhanden ist. Wenn wir Daten mit einer Eins-zu-Eins-Beziehung anstatt einer Eins-zu-Viele-Beziehung zusammenführen würden, wären diese flach, und Sie könnten einfach eine Reduzierungsfunktion wie die folgende verwenden:

reduce = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};

Wenn Sie die Auflistung users_comments Reduzieren möchten, sodass es sich um ein Dokument pro Kommentar handelt, führen Sie zusätzlich Folgendes aus:

var map, reduce;
map = function() {
    var debug = function(value) {
        var field;
        for (field in value) {
            print(field + ": " + value[field]);
        }
    };
    debug(this);
    var that = this;
    if ("comments" in this.value) {
        this.value.comments.forEach(function(value) {
            emit(value.commentId, {
                userId: that._id,
                country: that.value.country,
                age: that.value.age,
                comment: value.comment,
                created: value.created,
            });
        });
    }
};
reduce = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.users_comments.mapReduce(map, reduce, {"out": "comments_with_demographics"});

Diese Technik sollte auf keinen Fall im laufenden Betrieb durchgeführt werden. Es eignet sich für einen Cron-Job oder ähnliches, bei dem die zusammengeführten Daten regelmäßig aktualisiert werden. Wahrscheinlich möchten Sie ensureIndex für die neue Sammlung ausführen, um sicherzustellen, dass Abfragen, die Sie für sie durchführen, schnell ausgeführt werden (denken Sie daran, dass sich Ihre Daten immer noch in einem value Schlüssel befinden Sie sollten comments_with_demographics für die Zeit des Kommentars created indexieren, es wäre db.comments_with_demographics.ensureIndex({"value.created": 1});

140
rmarscher

MongoDB 3.2 ermöglicht es nun, Daten aus mehreren Sammlungen über die Aggregationsstufe $ lookup zu einer zu kombinieren. Nehmen wir als praktisches Beispiel an, Sie haben Daten zu Büchern, die in zwei verschiedene Sammlungen aufgeteilt sind.

Erste Sammlung mit dem Namen books mit den folgenden Daten:

{
    "isbn": "978-3-16-148410-0",
    "title": "Some cool book",
    "author": "John Doe"
}
{
    "isbn": "978-3-16-148999-9",
    "title": "Another awesome book",
    "author": "Jane Roe"
}

Und die zweite Sammlung namens books_selling_data mit folgenden Daten:

{
    "_id": ObjectId("56e31bcf76cdf52e541d9d26"),
    "isbn": "978-3-16-148410-0",
    "copies_sold": 12500
}
{
    "_id": ObjectId("56e31ce076cdf52e541d9d28"),
    "isbn": "978-3-16-148999-9",
    "copies_sold": 720050
}
{
    "_id": ObjectId("56e31ce076cdf52e541d9d29"),
    "isbn": "978-3-16-148999-9",
    "copies_sold": 1000
}

Um beide Sammlungen zusammenzuführen, müssen Sie lediglich $ lookup wie folgt verwenden:

db.books.aggregate([{
    $lookup: {
            from: "books_selling_data",
            localField: "isbn",
            foreignField: "isbn",
            as: "copies_sold"
        }
}])

Nach dieser Aggregation sieht die Sammlung books folgendermaßen aus:

{
    "isbn": "978-3-16-148410-0",
    "title": "Some cool book",
    "author": "John Doe",
    "copies_sold": [
        {
            "_id": ObjectId("56e31bcf76cdf52e541d9d26"),
            "isbn": "978-3-16-148410-0",
            "copies_sold": 12500
        }
    ]
}
{
    "isbn": "978-3-16-148999-9",
    "title": "Another awesome book",
    "author": "Jane Roe",
    "copies_sold": [
        {
            "_id": ObjectId("56e31ce076cdf52e541d9d28"),
            "isbn": "978-3-16-148999-9",
            "copies_sold": 720050
        },
        {
            "_id": ObjectId("56e31ce076cdf52e541d9d28"),
            "isbn": "978-3-16-148999-9",
            "copies_sold": 1000
        }
    ]
}

Es ist wichtig, einige Dinge zu beachten:

  1. Die "from" -Auflistung, in diesem Fall books_selling_data, kann nicht zerschmettert werden.
  2. Das Feld "as" ist wie im obigen Beispiel ein Array.
  3. Sowohl die Optionen "localField" als auch "foreignField" in der $ lookup-Phase werden für Übereinstimmungszwecke als null behandelt, wenn sie in ihren jeweiligen Sammlungen nicht vorhanden sind (die $ lookup docs = hat ein perfektes Beispiel dafür).

Wenn Sie also beide Sammlungen konsolidieren möchten und in diesem Fall ein flaches copy_sold-Feld mit den insgesamt verkauften Kopien haben, müssen Sie etwas mehr arbeiten, wahrscheinlich mit einer Zwischensammlung, die dann sei $ out zur endgültigen Sammlung.

110
Bruno Krebs

Wenn es in mongodb keine Masseneinfügung gibt, schleifen wir alle Objekte im small_collection und füge sie einzeln in das big_collection:

db.small_collection.find().forEach(function(obj){ 
   db.big_collection.insert(obj)
});
12
Hieu Le

Sehr einfaches Beispiel mit $ lookup.

db.getCollection('users').aggregate([
    {
        $lookup: {
            from: "userinfo",
            localField: "userId",
            foreignField: "userId",
            as: "userInfoData"
        }
    },
    {
        $lookup: {
            from: "userrole",
            localField: "userId",
            foreignField: "userId",
            as: "userRoleData"
        }
    },
    { $unwind: { path: "$userInfoData", preserveNullAndEmptyArrays: true }},
    { $unwind: { path: "$userRoleData", preserveNullAndEmptyArrays: true }}
])

Hier wird benutzt

 { $unwind: { path: "$userInfoData", preserveNullAndEmptyArrays: true }}, 
 { $unwind: { path: "$userRoleData", preserveNullAndEmptyArrays: true }}

Anstatt von

{ $unwind:"$userRoleData"} 
{ $unwind:"$userRoleData"}

Weil {$ unwind: "$ userRoleData"} dies leer zurückgibt oder 0 ergibt, wenn kein passender Datensatz mit $ lookup gefunden wurde.

10
Anish Agarwal

verwenden Sie multiple $ lookup für mehrere Sammlungen in Aggregation

Abfrage:

db.getCollection('servicelocations').aggregate([
  {
    $match: {
      serviceLocationId: {
        $in: ["36728"]
      }
    }
  },
  {
    $lookup: {
      from: "orders",
      localField: "serviceLocationId",
      foreignField: "serviceLocationId",
      as: "orders"
    }
  },
  {
    $lookup: {
      from: "timewindowtypes",
      localField: "timeWindow.timeWindowTypeId",
      foreignField: "timeWindowTypeId",
      as: "timeWindow"
    }
  },
  {
    $lookup: {
      from: "servicetimetypes",
      localField: "serviceTimeTypeId",
      foreignField: "serviceTimeTypeId",
      as: "serviceTime"
    }
  },
  {
    $unwind: "$orders"
  },
  {
    $unwind: "$serviceTime"
  },
  {
    $limit: 14
  }
])

Ergebnis:

{
    "_id" : ObjectId("59c3ac4bb7799c90ebb3279b"),
    "serviceLocationId" : "36728",
    "regionId" : 1.0,
    "zoneId" : "DXBZONE1",
    "description" : "AL HALLAB REST EMIRATES MALL",
    "locationPriority" : 1.0,
    "accountTypeId" : 1.0,
    "locationType" : "SERVICELOCATION",
    "location" : {
        "makani" : "",
        "lat" : 25.119035,
        "lng" : 55.198694
    },
    "deliveryDays" : "MTWRFSU",
    "timeWindow" : [ 
        {
            "_id" : ObjectId("59c3b0a3b7799c90ebb32cde"),
            "timeWindowTypeId" : "1",
            "Description" : "MORNING",
            "timeWindow" : {
                "openTime" : "06:00",
                "closeTime" : "08:00"
            },
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b0a3b7799c90ebb32cdf"),
            "timeWindowTypeId" : "1",
            "Description" : "MORNING",
            "timeWindow" : {
                "openTime" : "09:00",
                "closeTime" : "10:00"
            },
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b0a3b7799c90ebb32ce0"),
            "timeWindowTypeId" : "1",
            "Description" : "MORNING",
            "timeWindow" : {
                "openTime" : "10:30",
                "closeTime" : "11:30"
            },
            "accountId" : 1.0
        }
    ],
    "address1" : "",
    "address2" : "",
    "phone" : "",
    "city" : "",
    "county" : "",
    "state" : "",
    "country" : "",
    "zipcode" : "",
    "imageUrl" : "",
    "contact" : {
        "name" : "",
        "email" : ""
    },
    "status" : "ACTIVE",
    "createdBy" : "",
    "updatedBy" : "",
    "updateDate" : "",
    "accountId" : 1.0,
    "serviceTimeTypeId" : "1",
    "orders" : [ 
        {
            "_id" : ObjectId("59c3b291f251c77f15790f92"),
            "orderId" : "AQ18O1704264",
            "serviceLocationId" : "36728",
            "orderNo" : "AQ18O1704264",
            "orderDate" : "18-Sep-17",
            "description" : "AQ18O1704264",
            "serviceType" : "Delivery",
            "orderSource" : "Import",
            "takenBy" : "KARIM",
            "plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
            "plannedDeliveryTime" : "",
            "actualDeliveryDate" : "",
            "actualDeliveryTime" : "",
            "deliveredBy" : "",
            "size1" : 296.0,
            "size2" : 3573.355,
            "size3" : 240.811,
            "jobPriority" : 1.0,
            "cancelReason" : "",
            "cancelDate" : "",
            "cancelBy" : "",
            "reasonCode" : "",
            "reasonText" : "",
            "status" : "",
            "lineItems" : [ 
                {
                    "ItemId" : "BNWB020",
                    "size1" : 15.0,
                    "size2" : 78.6,
                    "size3" : 6.0
                }, 
                {
                    "ItemId" : "BNWB021",
                    "size1" : 20.0,
                    "size2" : 252.0,
                    "size3" : 11.538
                }, 
                {
                    "ItemId" : "BNWB023",
                    "size1" : 15.0,
                    "size2" : 285.0,
                    "size3" : 16.071
                }, 
                {
                    "ItemId" : "CPMW112",
                    "size1" : 3.0,
                    "size2" : 25.38,
                    "size3" : 1.731
                }, 
                {
                    "ItemId" : "MMGW001",
                    "size1" : 25.0,
                    "size2" : 464.375,
                    "size3" : 46.875
                }, 
                {
                    "ItemId" : "MMNB218",
                    "size1" : 50.0,
                    "size2" : 920.0,
                    "size3" : 60.0
                }, 
                {
                    "ItemId" : "MMNB219",
                    "size1" : 50.0,
                    "size2" : 630.0,
                    "size3" : 40.0
                }, 
                {
                    "ItemId" : "MMNB220",
                    "size1" : 50.0,
                    "size2" : 416.0,
                    "size3" : 28.846
                }, 
                {
                    "ItemId" : "MMNB270",
                    "size1" : 50.0,
                    "size2" : 262.0,
                    "size3" : 20.0
                }, 
                {
                    "ItemId" : "MMNB302",
                    "size1" : 15.0,
                    "size2" : 195.0,
                    "size3" : 6.0
                }, 
                {
                    "ItemId" : "MMNB373",
                    "size1" : 3.0,
                    "size2" : 45.0,
                    "size3" : 3.75
                }
            ],
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b291f251c77f15790f9d"),
            "orderId" : "AQ137O1701240",
            "serviceLocationId" : "36728",
            "orderNo" : "AQ137O1701240",
            "orderDate" : "18-Sep-17",
            "description" : "AQ137O1701240",
            "serviceType" : "Delivery",
            "orderSource" : "Import",
            "takenBy" : "KARIM",
            "plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
            "plannedDeliveryTime" : "",
            "actualDeliveryDate" : "",
            "actualDeliveryTime" : "",
            "deliveredBy" : "",
            "size1" : 28.0,
            "size2" : 520.11,
            "size3" : 52.5,
            "jobPriority" : 1.0,
            "cancelReason" : "",
            "cancelDate" : "",
            "cancelBy" : "",
            "reasonCode" : "",
            "reasonText" : "",
            "status" : "",
            "lineItems" : [ 
                {
                    "ItemId" : "MMGW001",
                    "size1" : 25.0,
                    "size2" : 464.38,
                    "size3" : 46.875
                }, 
                {
                    "ItemId" : "MMGW001-F1",
                    "size1" : 3.0,
                    "size2" : 55.73,
                    "size3" : 5.625
                }
            ],
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b291f251c77f15790fd8"),
            "orderId" : "AQ110O1705036",
            "serviceLocationId" : "36728",
            "orderNo" : "AQ110O1705036",
            "orderDate" : "18-Sep-17",
            "description" : "AQ110O1705036",
            "serviceType" : "Delivery",
            "orderSource" : "Import",
            "takenBy" : "KARIM",
            "plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
            "plannedDeliveryTime" : "",
            "actualDeliveryDate" : "",
            "actualDeliveryTime" : "",
            "deliveredBy" : "",
            "size1" : 60.0,
            "size2" : 1046.0,
            "size3" : 68.0,
            "jobPriority" : 1.0,
            "cancelReason" : "",
            "cancelDate" : "",
            "cancelBy" : "",
            "reasonCode" : "",
            "reasonText" : "",
            "status" : "",
            "lineItems" : [ 
                {
                    "ItemId" : "MMNB218",
                    "size1" : 50.0,
                    "size2" : 920.0,
                    "size3" : 60.0
                }, 
                {
                    "ItemId" : "MMNB219",
                    "size1" : 10.0,
                    "size2" : 126.0,
                    "size3" : 8.0
                }
            ],
            "accountId" : 1.0
        }
    ],
    "serviceTime" : {
        "_id" : ObjectId("59c3b07cb7799c90ebb32cdc"),
        "serviceTimeTypeId" : "1",
        "serviceTimeType" : "nohelper",
        "description" : "",
        "fixedTime" : 30.0,
        "variableTime" : 0.0,
        "accountId" : 1.0
    }
}
9
KARTHIKEYAN.A

Das Ausführen von Gewerkschaften in MongoDB in einer "SQL UNION" -Methode ist mithilfe von Aggregationen und Nachschlägen in einer einzigen Abfrage möglich. Hier ist ein Beispiel, das ich getestet habe und das mit MongoDB 4.0 funktioniert:

// Create employees data for testing the union.
db.getCollection('employees').insert({ name: "John", type: "employee", department: "sales" });
db.getCollection('employees').insert({ name: "Martha", type: "employee", department: "accounting" });
db.getCollection('employees').insert({ name: "Amy", type: "employee", department: "warehouse" });
db.getCollection('employees').insert({ name: "Mike", type: "employee", department: "warehouse"  });

// Create freelancers data for testing the union.
db.getCollection('freelancers').insert({ name: "Stephany", type: "freelancer", department: "accounting" });
db.getCollection('freelancers').insert({ name: "Martin", type: "freelancer", department: "sales" });
db.getCollection('freelancers').insert({ name: "Doug", type: "freelancer", department: "warehouse"  });
db.getCollection('freelancers').insert({ name: "Brenda", type: "freelancer", department: "sales"  });

// Here we do a union of the employees and freelancers using a single aggregation query.
db.getCollection('freelancers').aggregate( // 1. Use any collection containing at least one document.
  [
    { $limit: 1 }, // 2. Keep only one document of the collection.
    { $project: { _id: '$$REMOVE' } }, // 3. Remove everything from the document.

    // 4. Lookup collections to union together.
    { $lookup: { from: 'employees', pipeline: [{ $match: { department: 'sales' } }], as: 'employees' } },
    { $lookup: { from: 'freelancers', pipeline: [{ $match: { department: 'sales' } }], as: 'freelancers' } },

    // 5. Union the collections together with a projection.
    { $project: { union: { $concatArrays: ["$employees", "$freelancers"] } } },

    // 6. Unwind and replace root so you end up with a result set.
    { $unwind: '$union' },
    { $replaceRoot: { newRoot: '$union' } }
  ]);

Hier ist die Erklärung, wie es funktioniert:

  1. Instanziieren Sie ein aggregate aus beliebig Ihrer Datenbank, die mindestens ein Dokument enthält. Wenn Sie nicht garantieren können, dass eine Sammlung Ihrer Datenbank nicht leer ist, können Sie dieses Problem umgehen, indem Sie in Ihrer Datenbank eine Art 'Dummy'-Sammlung erstellen, die ein einzelnes leeres Dokument enthält, das speziell für Unionsabfragen zur Verfügung steht.

  2. Machen Sie den ersten Schritt Ihrer Pipeline zu { $limit: 1 }. Dadurch werden alle Dokumente der Sammlung mit Ausnahme des ersten entfernt.

  3. Entfernen Sie alle Felder des verbleibenden Dokuments mithilfe einer Stufe $project:

    { $project: { _id: '$$REMOVE' } }
    
  4. Ihr Aggregat enthält jetzt ein einzelnes, leeres Dokument. Es ist Zeit, Lookups für jede Sammlung hinzuzufügen, die Sie zusammenführen möchten. Sie können das Feld pipeline verwenden, um eine bestimmte Filterung durchzuführen, oder localField und foreignField als Nullwert belassen, um die gesamte Sammlung abzugleichen.

    { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
    { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
    { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
    
  5. Sie haben jetzt ein Aggregat, das ein einzelnes Dokument enthält, das drei Arrays wie das folgende enthält:

    {
        Collection1: [...],
        Collection2: [...],
        Collection3: [...]
    }
    

    Sie können sie dann unter Verwendung einer Stufe $project Zusammen mit dem Aggregationsoperator $concatArrays Zu einem einzigen Array zusammenführen:

    {
      "$project" :
      {
        "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
      }
    }
    
  6. Sie haben jetzt ein Aggregat, das ein einzelnes Dokument enthält, in dem sich ein Array befindet, das Ihre Zusammenstellung von Sammlungen enthält. Was zu tun bleibt, ist das Hinzufügen einer Stufe $unwind Und einer Stufe $replaceRoot, Um Ihr Array in separate Dokumente aufzuteilen:

    { $unwind: "$Union" },
    { $replaceRoot: { newRoot: "$Union" } }
    
  7. Voilà. Sie haben jetzt eine Ergebnismenge mit den Sammlungen, die Sie zusammenführen möchten. Sie können dann weitere Stufen hinzufügen, um sie weiter zu filtern, zu sortieren, skip () und limit () anzuwenden. So ziemlich alles was du willst.

3
sboisse

Mongorestore hat diese Funktion, die über alles angehängt wird, was sich bereits in der Datenbank befindet. Daher kann dieses Verhalten zum Kombinieren von zwei Sammlungen verwendet werden:

  1. mongodump collection1
  2. collection2.rename (collection1)
  3. mongorestore

Ich habe es noch nicht ausprobiert, aber es ist möglicherweise schneller als der Karten-/Reduktionsansatz.

2
shauli

Code-Auszug. Mit freundlicher Genehmigung - Mehrere Posts auf Stapelüberlauf, einschließlich dieser.

 db.cust.drop();
 db.Zip.drop();
 db.cust.insert({cust_id:1, Zip_id: 101});
 db.cust.insert({cust_id:2, Zip_id: 101});
 db.cust.insert({cust_id:3, Zip_id: 101});
 db.cust.insert({cust_id:4, Zip_id: 102});
 db.cust.insert({cust_id:5, Zip_id: 102});

 db.Zip.insert({Zip_id:101, Zip_cd:'AAA'});
 db.Zip.insert({Zip_id:102, Zip_cd:'BBB'});
 db.Zip.insert({Zip_id:103, Zip_cd:'CCC'});

mapCust = function() {
    var values = {
        cust_id: this.cust_id
    };
    emit(this.Zip_id, values);
};

mapZip = function() {
    var values = {
    Zip_cd: this.Zip_cd
    };
    emit(this.Zip_id, values);
};

reduceCustZip =  function(k, values) {
    var result = {};
    values.forEach(function(value) {
    var field;
        if ("cust_id" in value) {
            if (!("cust_ids" in result)) {
                result.cust_ids = [];
            }
            result.cust_ids.Push(value);
        } else {
    for (field in value) {
        if (value.hasOwnProperty(field) ) {
                result[field] = value[field];
        }
         };  
       }
      });
       return result;
};


db.cust_Zip.drop();
db.cust.mapReduce(mapCust, reduceCustZip, {"out": {"reduce": "cust_Zip"}});
db.Zip.mapReduce(mapZip, reduceCustZip, {"out": {"reduce": "cust_Zip"}});
db.cust_Zip.find();


mapCZ = function() {
    var that = this;
    if ("cust_ids" in this.value) {
        this.value.cust_ids.forEach(function(value) {
            emit(value.cust_id, {
                Zip_id: that._id,
                Zip_cd: that.value.Zip_cd
            });
        });
    }
};

reduceCZ = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.cust_Zip_joined.drop();
db.cust_Zip.mapReduce(mapCZ, reduceCZ, {"out": "cust_Zip_joined"}); 
db.cust_Zip_joined.find().pretty();


var flattenMRCollection=function(dbName,collectionName) {
    var collection=db.getSiblingDB(dbName)[collectionName];

    var i=0;
    var bulk=collection.initializeUnorderedBulkOp();
    collection.find({ value: { $exists: true } }).addOption(16).forEach(function(result) {
        print((++i));
        //collection.update({_id: result._id},result.value);

        bulk.find({_id: result._id}).replaceOne(result.value);

        if(i%1000==0)
        {
            print("Executing bulk...");
            bulk.execute();
            bulk=collection.initializeUnorderedBulkOp();
        }
    });
    bulk.execute();
};


flattenMRCollection("mydb","cust_Zip_joined");
db.cust_Zip_joined.find().pretty();
0
Vipul Mehta

Ja, Sie können: Nehmen Sie diese Utility-Funktion, die ich heute geschrieben habe:

function shangMergeCol() {
  tcol= db.getCollection(arguments[0]);
  for (var i=1; i<arguments.length; i++){
    scol= db.getCollection(arguments[i]);
    scol.find().forEach(
        function (d) {
            tcol.insert(d);
        }
    )
  }
}

Sie können beliebig viele Sammlungen an diese Funktion übergeben, wobei die erste die Zielsammlung sein wird. Alle übrigen Sammlungen sind Quellen, die auf die Zielsammlung übertragen werden sollen.

0
Shangab