var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var schema = new Schema({
title: String,
nbPages: Number,
language: {
type: String,
enum: ['en', 'fr', 'es']
},
kind: {
type: String,
enum: ['action', 'drama', 'comedy', 'detective', 'love']
},
});
var getKindConditions = function () {
return {
$or: [
// I can read anything in english...
{
language: 'en'
},
// ...but would prefer love stories in french...
{
language: 'fr',
kind: 'love'
},
// ...or comedy ones in spanish.
{
language: 'es',
kind: 'comedy'
},
]
};
}
schema.methods.findBooksToRead = function(callback) {
var query = this.model('Books').find({
// Initial conditions.
$or: [
// I can read big books in english...
{
nbPages: { $gt: 300 },
language: 'en'
},
// ...but I'm still learning french and spanish.
{
nbPages: { $lte: 300 },
language: { $or: ['fr', 'es'] }
}
]
});
var kindConditions = getKindConditions();
// Additionnal conditions.
query.where(kindConditions);
query.exec(callback);
});
module.exports = mongoose.model('Books', schema);
通过这个例子,我搞砸了。我在设置$or
时添加的query.where(kindConditions)
运算符将覆盖我放置在$or
中的this.model('Books').find(...)
运算符。
Mongoose where
函数是否应将所有新元素视为$and
?
这是我的解决方法(推送$and
逻辑查询运算符中的所有新条件:
schema.methods.findBooksToRead = function(callback) {
var conditions = {
$and: []
};
// Initial conditions.
conditions.$all.push({
$or: [
// I can read big books in english...
{
nbPages: { $gt: 300 },
language: 'en'
},
// ...but I'm still learning french and spanish.
{
nbPages: { $lte: 300 },
language: { $or: ['fr', 'es'] }
}
]
});
var kindConditions = getKindConditions();
// Additionnal conditions.
conditions.$all.push(kindConditions);
var query = this.model('Books').find(conditions);
query.exec(callback);
});
module.exports = mongoose.model('Books', schema);
答案 0 :(得分:1)
是的,它适合Mongoose这样做。您在构建查询的两个(某种程度上)互斥的样式之间遇到问题:使用QueryBuilder而不使用。
在回调样式(即不是QueryBuilder)中,不需要query.exec
,你可以直接传递回调:
var query = this.model('Books').find(conditions, callback);
此查询将立即执行。但是,如果您没有给它回调,那么您将获得一个具有QueryBuilder接口的Query对象,您可以使用where
,{{{{}}等操作逐步构建您的查询1}},all
,and
等
or
您的第二个示例有效,并且效果更好,因为它在应用条件的样式中是一致的。您可以使用其他样式(使用var query = this.model('Books').find();
query.where({ something: true }); // This must match
query.where({ somethingElse: false }); // AND this must match
query.exec();
并从条件对象中删除它),只需了解QueryBuilder上的执行函数正在修改/构建查询,每次调用其函数之一。
此外,query.or
用于链接路径。它会抓住您的对象并提供检查标准的快捷方式。如果你写这样的东西,它会更清楚:
where
所以:坚持使用你的第二段代码(可能对数组中的每个项目使用新的query.where('language').equals('en');
调用而不是顶级where
),或者重做前者以排除查询操作在$and
来电,然后使用find
进行构建。
答案 1 :(得分:0)
我尝试使用query.or
和QueryBuilder进行重建,但也可以覆盖和合并$or
条件。
query.where
($or
被覆盖)正如@adam-terlson所说,将方法混淆不是一个好主意,但是,正如我们所做的那样,看看我们这样做会发生什么事情会很有趣。 / p>
var query = this.model('Books').find();
// First "or" conditions.
query.where({
$or: [
{ nbPages: { $gt: 300 }, language: 'en' },
{ nbPages: { $lte: 300 }, language: { $or: ['fr', 'es'] } }
]
});
// Second "or" conditions.
query.where({
$or: [
{ language: 'en' },
{ language: 'fr', kind: 'love' },
{ language: 'es', kind: 'comedy' }
]
});
query.exec(callback);
在我的query._conditions
中,我可以看到where
函数覆盖我的第一个$or
条件。
{
$or: [
{ language: 'en' },
{ language: 'fr', kind: 'love' },
{ language: 'es', kind: 'comedy' }
]
}
query.or
($or
已合并)var query = this.model('Books').find();
// First "or" conditions.
query.or([
{ nbPages: { $gt: 300 }, language: 'en' },
{ nbPages: { $lte: 300 }, language: { $or: ['fr', 'es'] } }
]);
// Second "or" conditions.
query.or([
{ language: 'en' },
{ language: 'fr', kind: 'love' },
{ language: 'es', kind: 'comedy' }
]);
query.exec(callback);
在我的query._conditions
中,我可以看到or
功能为合并我的$or
条件。
{
$or: [
{ nbPages: { $gt: 300 }, language: 'en' },
{ nbPages: { $lte: 300 }, language: { $or: ['fr', 'es'] } },
{ language: 'en' },
{ language: 'fr', kind: 'love' },
{ language: 'es', kind: 'comedy' }
]
}
query.and
(附加$or
)因此,如果您需要2个或更多不同的$or
条件集,则无法在查询中构建它。您必须将所有$or
条件放在一起,然后使用and
函数。
var query = this.model('Books').find();
var orConditions = [];
// First "or" conditions.
orConditions.push({
$or: [
{ nbPages: { $gt: 300 }, language: 'en' },
{ nbPages: { $lte: 300 }, language: { $or: ['fr', 'es'] } }
]
});
// Second "or" conditions.
orConditions.push({
$or: [
{ language: 'en' },
{ language: 'fr', kind: 'love' },
{ language: 'es', kind: 'comedy' }
]
});
query.and(orConditions);
query.exec(callback);