【问题标题】:Does mongoose / mongodb have access to object references in schema during aggregate?mongoose / mongodb 在聚合期间是否可以访问模式中的对象引用?
【发布时间】:2016-03-18 01:34:16
【问题描述】:

我正在处理一个查询,该查询从我的 mongo 数据库中的 2 个不同的 obj 引用中读取。我将使用一个简单的例子来说明我在寻找什么。

我有 3 个架构:

User = new Schema({
    places:[{type: Schema.Types.ObjectId, ref:'Place'}],
    shouts:[{type: Schema.Types.ObjectId, ref:'Shout'}]
});
Place = new Schema({
    name:String,
    description:String,
});
Shout = new Schema({
    content:String,
});

我最大的问题是 mongoose 或 mongodb 在执行聚合方法时是否可以访问 objectId 引用。请允许我详细说明。

module.exports.askForShoutInPlace = function(req, res){
    var pname = new RegExp(req.params.pname, 'i'); 
    User.aggregate(
        [
           {'$match':{ 'places':{
               '$elemMatch':{'name':pname}
                }
           },
           {'$project':{ shout:'$shouts'} },
           {'$unwind':'$shouts'},
           {'$group':{_id:'$shouts'}}
        ]).exec(function(err, results){
        res.send(results);
    });

}

这通常可以正常工作,但是一旦调用 $match 运算符,我就会得到一个空数组,我猜它与返回未定义子对象的对象引用有关。有什么解决办法吗?或者这是否意味着我必须采取另一条路线来雇用人口?

提前感谢大家的帮助

【问题讨论】:

  • 您可能想阅读 - mongoosejs.com/docs/populate.html。您需要在客户端解析引用。 Mongoose 使用 populate 功能为您做这件事。 aggregation 代码在服务器端执行,因此不会自动解析引用。
  • 感谢@BatScream 的回复,这只是一个了解错误基本原理的示例,我正在使用地理空间索引,因此在客户端解决这个问题可能比需要的更难。假设,如果子模式将引用父模式,您是否说可以聚合子模式,填充父模式并在将结果发送给客户端之前进行过滤?或者这会被证明是一个糟糕的性能瓶颈?

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

在聚合过程中无法访问对象引用的数据,我为我的项目采用的解决方法是在相关架构中添加对所有者的引用。

User = new Schema({
    places:[{type: Schema.Types.ObjectId, ref:'Place'}],
    shouts:[{type: Schema.Types.ObjectId, ref:'Shout'}]
});
Place = new Schema({
    owner:{type: Schema.Types.ObjectId, ref:'Place'},
    name:String,
    description:String,
});
Shout = new Schema({
    owner:{type: Schema.Types.ObjectId, ref:'Place'},
    content:String,
});

然后直接在子文档上进行聚合,得到拥有地点实例的唯一用户,这样就可以得到一个查询和地点匹配的喊话结果。

例子:

module.exports.askForShoutInPlace = function(req, res){
var pname = new RegExp(req.params.pname, 'i'); 
var stringQ = new RegExp(req.paramos.qcontent, 'i');
Place.aggregate(
    [
       //find Places that match criteria
       {'$match':{'name':pname}},
       //select owner id object to result
       {'$project':{ owner:'$owner'}},
       //group those results to single array with unique ids of users
       {'$group':{_id:'$owner'}}
    ]).exec(function(err, results){
    //find user shouts that match string and belong to owners know to be owners of a place
    Shout.find({'content':stringQ}).where({'owner':{'$in':results}}).exec(function(err, shouts){
       res.send(shouts);
    });
});

}

这只是我发现解决我的特殊需求的方法,我希望它可以帮助某人。

【讨论】:

    猜你喜欢
    • 2013-07-02
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-04-10
    • 2016-04-29
    • 2019-04-15
    • 2013-12-29
    • 1970-01-01
    相关资源
    最近更新 更多