假设我有一组用户名和电子邮件地址的用户。
{ name: 'John Doe', email: 'john@doe.com', level: 5 }
{ name: 'Fred Foo', email: 'fred@foo.com', level: 2 }
{ name: 'Jo Green', email: 'jo@green.com', level: 5 }
{ name: 'Paul Bar', email: 'paul@bar.com', level: 3 }
我想查询此集合,选择所有用户的名称和级别。在Mongoose,我可以这样做:
User
.find()
.select('name level')
.exec(callback)
这会给我以下内容:
{ name: 'John Doe', level: 5 }
{ name: 'Fred Foo', level: 2 }
{ name: 'Jo Green', level: 5 }
{ name: 'Paul Bar', level: 3 }
但如果用户的级别高于4,我还想获得他们的电子邮件地址。这会给我以下内容:
{ name: 'John Doe', email: 'john@doe.com', level: 5 }
{ name: 'Fred Foo', level: 2 }
{ name: 'Jo Green', email: 'paul@bar.com', level: 5 }
{ name: 'Paul Bar', level: 3 }
Mongo [ose]的最佳效果是什么?
答案 0 :(得分:4)
不,MongoDb目前在一个查询中没有根据条件选择性地返回不同的字段集。 MongoDb中的查询和关联的投影适用于所有文档。
map reduce不能这样做(因为map reduce需要为每个文档返回相同的值)并且不合适。聚合不是许多查询的通用替代方法,并且有条件地返回字段会很复杂。
您有几个选择:
我会测试选项的性能。两者都不复杂。
答案 1 :(得分:1)
正如WiredPrairie所说,这在一个查询中是不可能的。使用聚合和一些应用程序代码可以轻松完成。要仅返回级别高于4的电子邮件,以下聚合将起作用:
User.aggregate().match({})
.project({
'name': 1,
'email': {
$cond: {
if: {
'$gt': ['$level', 4]
},
then: '$email',
else: null
}
},
'level': 1
})
.exec(callback);
使用lodash或underscore等实用程序库可以直接删除结果集中的任何空电子邮件。在回调函数中,以下lodash函数将删除任何空电子邮件:
var callback = function(err, users) {
return _.map(users, function(user) {
return _.omitBy(user, _.isNull);
});
};