【问题标题】:How to match the onther collection data in mongodb如何匹配mongodb中的其他集合数据
【发布时间】:2016-01-22 12:15:30
【问题描述】:

我叫 Brighton,是一名 Android 开发人员。最近一直在研究MongoDB数据库,这对我来说非常困难,需要你的帮助。

第一个集合

{
    "_id" : ObjectId("5628c5b27ad4a27341f7be6d"),
    "name" : "Ace",
    "address" : "Seuol",
    "reservations" : [ 
        {
            "token" : "f59c6e0a99dabbe2b954bf9fd31bc23e1c07b6079345aa84255ad5e6d457fd523e1387048dd9a31392bfd25dbe6c093386dff31904d20064d7981ef2da4ab11d",
            "productnumber" : 2
        }
    ]
}

SecondCollection

{
    "_id" : ObjectId("561710b47ad4a27341f7be18"),
    "productnumber" : 2,
    "productprice" : "47",
    "category" : "Fix",
    "name" : "Oil"
}

我想得到一个结果,它仅使用查找查询将FirstCollection 中的productnumber 的值替换为SecondCollection 中的实际文档。这是预期的结果

{
    "_id" : ObjectId("5628c5b27ad4a27341f7be6d"),
    "name" : "Ace",
    "address" : "Seuol",
    "reservations" : [
        {
            "token" : "f59c6e0a99dabbe2b954bf9fd31bc23e1c07b6079345aa84255ad5e6d457fd523e1387048dd9a31392bfd25dbe6c093386dff31904d20064d7981ef2da4ab11d",
            "productnumber" : {
                "_id" : ObjectId("561710b47ad4a27341f7be18"),
                "productnumber" : 2,
                "productprice" : "47",
                "category" : "Fix",
                "name" : "Oil"
            }
        }
    ]
}

如何输入查询?我找不到任何解决方案。当我输入数据时,我必须输入所有这些数据吗?

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    根据您问题中的标签,您需要对两个集合进行异步调用,因为您希望使用 Mongoose 获得结果。要理解这个概念,请考虑 mongo shell 中的操作。

    使用 mongo Shell 中的解决方案,从 find() 方法迭代光标以访问 FirstCollection 中的文档并使用原生 JavaScript 方法操作 reservations 数组 map(),使用 SecondCollection 上的 findOne() 方法获取新值。类似于 mongo Shell 中的以下代码:

    var cur = db.reservation.find({"reservations": { "$exists": true, "$type": 4 } });
    cur.forEach(function (doc){
        var reservations = doc.reservations.map(function (r){
            var product = db.product.findOne({"productnumber": r.productnumber});
            return { 
                "token": r.token,        
                "productnumber": product
            }
        });
        doc.reservations = reservations;
        printjson(doc);
    })
    

    对于给定的样本数据,这将打印:

    {
        "_id" : ObjectId("5628c5b27ad4a27341f7be6d"),
        "name" : "Ace",
        "address" : "Seuol",
        "reservations" : [
            {
                "token" : "f59c6e0a99dabbe2b954bf9fd31bc23e1c07b6079345aa84255ad5e6d457fd523e1387048dd9a31392bfd25dbe6c093386dff31904d20064d7981ef2da4ab11d",
                "productnumber" : {
                    "_id" : ObjectId("561710b47ad4a27341f7be18"),
                    "productnumber" : 2,
                    "productprice" : "47",
                    "category" : "Fix",
                    "name" : "Oil"
                }
            }
        ]
    }
    

    对于 Mongoose 中的解决方案,您需要在 find() 查询上的 exec() 之前调用 lean() 方法,因为文档从精益查询返回启用的选项是纯 javascript 对象, 因此,您可以通过将productnumber 字段值替换为SecondCollection 中的文档来操作文档

    来自猫鼬documentation

    Model.find().lean().exec(function (err, docs) {
        docs[0] instanceof mongoose.Document // false
    });
    

    所以您的代码应该如下所示(假设 Reservation 模型指的是 FirstCollection 和 Product 模型指的是 SecondCollection ):

    var Reservation = mongoose.model('reservations');
    var Product = mongoose.model('product');
    
    Reservation.find()
        .lean()
        .exec(function (err, docs) {
            if(err) return res.send(err);
    
            async.forEach(docs, function(doc, done) {
                _.each(doc.reservations, function(resv, i) {
                    Product.findOne()
                            .where('productnumber')
                            .equals(resv.productnumber)
                            .lean()
                            .exec(function(err, product) {
                                resv.productnumber = product;
                                done(err);
                            });             
                });         
            }, function(err) {
                // ... you have reservations with products
                console.log(docs[0]);           
                // res.send(docs);      
            });        
        });
    

    【讨论】:

    • 感谢您的教导,所以我确实尝试了第一个示例,但发生错误 2015-10-25T08:31:48.284+0000 TypeError: Cannot call method 'map' of undefined
    • 我想我知道为什么,您的某些文档没有 reservations 字段,因此循环中的 map() 方法在尝试映射现有数组字段时抛出错误。我编辑了我的答案以纠正这个问题。此外,阅读this 会有所帮助。
    【解决方案2】:

    在您的架构中将 ref 添加到另一个集合

    "reservations" : [{
            "token" : String,
            "productnumber" : {type:Number, ref:'secendCollection'}
        }]
    

    并使用猫鼬填充

    schema.find({your query}).populate('reservations.productnumber').exec(callback function)
    

    see the docs

    【讨论】:

      猜你喜欢
      • 2015-04-06
      • 2022-11-07
      • 2020-10-24
      • 2018-02-12
      • 2019-08-04
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多