为什么query.where()函数将每个条件视为" $和"?

时间:2015-05-28 14:57:56

标签: mongodb mongoose

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);

2 个答案:

答案 0 :(得分:1)

是的,它适合Mongoose这样做。您在构建查询的两个(某种程度上)互斥的样式之间遇到问题:使用QueryBuilder而不使用。

在回调样式(即不是QueryBuilder)中,不需要query.exec,你可以直接传递回调:

var query = this.model('Books').find(conditions, callback);

此查询将立即执行。但是,如果您没有给它回调,那么您将获得一个具有QueryBuilder接口的Query对象,您可以使用where,{{{{}}等操作逐步构建您的查询1}},alland

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);