Mongodb:用于基于嵌套文档将两个架构的数据连接起来的聚合/ Pipilines

时间:2018-07-18 07:18:47

标签: node.js mongodb mongoose nested-documents

这是我的架构:

var mongoose = require('mongoose');

var EventSchema = new mongoose.Schema({
    name: {type:String},
    start_date: {type:Date},
    duration: {type:String},
    event_id:{type: mongoose.Schema.Types.ObjectId}
});
var Project = new mongoose.Schema({
    name: {
        type: String, 
        required: '{PATH} is required!'
    },
    user_id:{
        type: mongoose.Schema.Types.ObjectId,
        required:'{PATH} is required!'
    },
    client: {type: Object},
    no_of_events: {type: String, required: '{PATH} is required!'},
    start_date:{type:Date, required: '{PATH} is required!'},
    end_date:{type:Date, required: '{PATH} is required!'},
    budget:{type: String},
    groom:{type:Object},
    bride:{type:Object},
    events:[EventSchema],
    status:{type:Number,Default:1}, //0=Inactive, 1=Active, 2=Completed
    created_at: { type: Date, default: Date.now },
    updated_at: { type: Date, default: Date.now }
});

module.exports = mongoose.model('Project', Project);

在创建Project时,我要添加多个事件。因此,在“事件”中存在对象数组。这是示例数据:

{
    "_id": {
        "$oid": "5b43582a716d9a4e96345f4a"
    },
    "bride": {
        "city": "Hyderabad",
        "phone": "09876543211",
        "dob": "1993-05-06T18:30:00.000Z",
        "name": "Shriya Bhupal"
    },
    "groom": {
        "city": "Hyderabad",
        "phone": "09876543211",
        "dob": "1993-08-09T18:30:00.000Z",
        "name": "Anindith Reddy"
    },
    "client": {
        "name": "Apoorva Pagar"
    },
    "end_date": {
        "$date": "2018-07-22T18:30:00.000Z"
    },
    "start_date": {
        "$date": "2018-07-10T18:30:00.000Z"
    },
    "no_of_events": "4",
    "user_id": {
        "$oid": "5b126966bcc8072e526346ad"
    },
    "name": "Big Fat Wedding",
    "updated_at": {
        "$date": "2018-07-09T12:42:18.263Z"
    },
    "created_at": {
        "$date": "2018-07-09T12:42:18.263Z"
    },
    "events": [
        {
            "name": "Engagement",
            "event_id": {
                "$oid": "5b3b232914cdec23c19c034c"
            },
            "start_date": {
                "$date": "2018-07-11T18:30:00.000Z"
            },
            "duration": "1 Day",
            "_id": {
                "$oid": "5b43582a716d9a4e96345f4b"
            }
        },
        {
            "name": "Mehndi",
            "event_id": {
                "$oid": "5b3b23b314cdec23c19c034d"
            },
            "start_date": {
                "$date": "2018-07-12T18:30:00.000Z"
            },
            "duration": "1 Day",
            "_id": {
                "$oid": "5b43582a716d9a4e96345f4c"
            }
        },
        {
            "name": "Sangeet",
            "event_id": {
                "$oid": "5b3b232914cdec23c19c034c"
            },
            "start_date": {
                "$date": "2018-07-17T18:30:00.000Z"
            },
            "duration": "2 Days",
            "_id": {
                "$oid": "5b43582a716d9a4e96345f4d"
            }
        }
    ],
    "__v": 0
}

在这种情况下,如果我从默认事件中添加事件,则有event_id,否则没有event_id。因此,如果添加了默认事件,这些默认事件将保存在另一个名为“ defaultevents”的架构中。现在,如果数据中存在event_id,我想在每个事件对象中添加eventdetail。

    {"events": [
            {
// it should include event_detail:{ details about event from defaultevents}
                "name": "Engagement",
                "event_id": {
                    "$oid": "5b3b232914cdec23c19c034c"
                },
                "start_date": {
                    "$date": "2018-07-11T18:30:00.000Z"
                },
                "duration": "1 Day",
                "_id": {
                    "$oid": "5b43582a716d9a4e96345f4b"
                }
            },
            {
// it should not include event_details as there is no event_id
                "name": "Mehndi",
                "start_date": {
                    "$date": "2018-07-12T18:30:00.000Z"
                },
                "duration": "1 Day",
                "_id": {
                    "$oid": "5b43582a716d9a4e96345f4c"
                }
            }
    ]
    }

DefaultEvents Sameple数据:

{
    "_id": {
        "$oid": "5b3b232914cdec23c19c034c"
    },
    "image": "https://dostbucket.s3.us-east-2.amazonaws.com/events/1530601666360mehndi.svg",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
    "name": "Sangeet",
    "updated_at": {
        "$date": "2018-07-03T07:18:01.166Z"
    },
    "created_at": {
        "$date": "2018-07-03T07:18:01.166Z"
    },
    "__v": 0
}

mongod版本:3.4.7(MMAPv1)

3 个答案:

答案 0 :(得分:1)

您可以通过$lookup聚合来实现

db.colletion.aggregate([
  { "$unwind": "$events" },
  { "$lookup": {
    "from": DefaultEventSchema.collection.name,
    "localField": "events.event_id",
    "foreignField": "_id",
    "as": "events.event_id"
  }},
  { "$unwind": { "path": "$events.event_id", "preserveNullAndEmptyArrays": true } },
  { "$group": {
    "_id": "$_id",
    "events": { "$push": "$events" },
    "bride": { "$first": "$bride" },
    "groom": { "$first": "$groom" },
    "client": { "$first": "$client" },
    "end_date": { "$first": "$end_date" },
    "no_of_events": { "$first": "$no_of_events" },
    "name": { "$first": "$name" },
    "created_at": { "$first": "$created_at" },
    "updated_at": { "$first": "$updated_at" }
  }}
])

答案 1 :(得分:1)

您可以在3.6中使用以下汇总。

ProjectModel.aggregate([
  {"$unwind":"$events"},
  {"$lookup":{
    "from": "event", //name of the foreign collection not model or schema name
    "localField": "events.event_id",
    "foreignField": "_id",
    "as": "events.eventdetail"
  }},
  {"$unwind":{"path":"$events.eventdetail", "preserveNullAndEmptyArrays":true }}, // Keep non matching events
  {"$group":{
    "_id": "$_id",
    "events": { "$push": "$events" },
    "data": { "$first": "$$ROOT" } // $$ROOT to keep the entire data
  }},
  {"$addFields":{"data.events":"$events", "events":0}}, // Replace the events  with grouped events.
  {"$replaceRoot":{"newRoot":"$data"}}
])

答案 2 :(得分:0)

Simerjit,因为mongo不提供$(定位运算符)来搜索和更新对象数组(如果我们尝试这样做,则只会更新第一个对象read more here),因此我们需要在通过以下方式:

var products = Product.find();

products.forEach(product => {
    product.events.forEach(event => {
        if ('event_id' in event) {
            var product = product.events[event];
            product.event.event_details = 'my details';
            product.save(product);
        }
    });
});

您可能需要对代码进行一些调整,但是我希望它可以使您了解如何实现所需的内容。