如何使用sails-mongodb获取'和'查询

时间:2016-09-03 06:24:00

标签: node.js mongodb express sails.js

我有一个在mongo shell中工作的查询

db.getCollection('insights').find({$and:[{author:/jim/i}]})

返回2条记录。

'或'代码调用waterline / sailsjs-mongo

db('insights').find({
    or: [
        {or: [ {author: new RegExp( ".*"+"jim"+".*", 'i' )} ] }
    ]
    }).limit(req.params.limit).skip(req.params.offset).exec(function (err, insights) { ... }

按预期返回2条记录。

如果我将'或'更改为'和'

db('insights').find({
    or: [
        {and: [ {author: new RegExp( ".*"+"jim"+".*", 'i' )} ] }
    ]
    }).limit(req.params.limit).skip(req.params.offset).exec(function (err, insights) { ... }

我得到0条记录,这是不可预期的。它应该返回2条记录。

我使用原生mongodb javascript客户端编写了一些代码。

var MongoClient = require('mongodb').MongoClient,
  test = require('assert');
// Connection url
var url = 'mongodb://localhost:27017/infosystem';
// Connect using MongoClient
MongoClient.connect(url, function(err, db) {
  // Create a collection we want to drop later
  var col = db.collection('insights');
  // Show that duplicate records got dropped
  col.find({$and:[{author: new RegExp('.*Jim.*','i')}]}).toArray(function(err, items) {
    test.equal(null, err);
    test.equal(2, items.length);
    db.close();
  });
});

当运行时不会抛出任何断言。

 node test_insights.js

mongodb是版本3.2.9,sails-mongodb和水线是版本“0.12.1”

在sails-mongodb中调用mongodb $和查询的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

https://docs.mongodb.com/manual/reference/operator/query/and/#and

  

$并对两个或更多的数组执行逻辑AND运算   表达式(例如expression1,expression2等)并选择   满足数组中所有表达式的文档。 $和   操作员使用短路评估。如果是第一个表达式(例如   expression1)计算结果为false,MongoDB不会评估   剩下的表达。

所以在你的情况下,使用AND运算符甚至没有意义,因为你也可以使用隐式AND,比如

db.getCollection('insights').find({author:/jim/i})

来解决你的实际问题。我无法使用本机mongodb重现此问题。在shell中:

db.collection.insert({name:'Foo', age:28})
db.collection.insert({name:'Bar', age:32})

db.collection.find()
{ "_id" : ObjectId("57ca84c374f2776cc983ad9e"), "name" : "Foo", "age" : 28 }
{ "_id" : ObjectId("57ca84cd74f2776cc983ad9f"), "name" : "Bar", "age" : 32 }

db.collection.find({$and:[{name:new RegExp('.*Fo.*','i')}]})
{ "_id" : ObjectId("57ca84c374f2776cc983ad9e"), "name" : "Foo", "age" : 28 }

> db.collection.find({$or:[{$or:[{name:new RegExp('.*Fo.*','i')}]}]})
{ "_id" : ObjectId("57ca84c374f2776cc983ad9e"), "name" : "Foo", "age" : 28 }

> db.collection.find({$or:[{$and:[{name:new RegExp('.*Fo.*','i')}]}]})
{ "_id" : ObjectId("57ca84c374f2776cc983ad9e"), "name" : "Foo", "age" : 28 }

我得到了预期的结果。但是,当我尝试使用嵌套的水线查询和/或我看到你描述的相同问题。让我们看看以下原生查询:

db.collection.find({$or:[{$and:[{name:'Foo'}, {age:28}]}, {name:'Bar'}]})

正确返回:

{ "_id" : ObjectId("57ca84c374f2776cc983ad9e"), "name" : "Foo", "age" : 28 }
{ "_id" : ObjectId("57ca84cd74f2776cc983ad9f"), "name" : "Bar", "age" : 32 }

现在让我们在水线中创建相同的查询:

Test.find({
    or: [
        {and: [{name:'Foo'},{age:28}]},
        {name: 'Bar'}
    ]
})

这会返回[]。可以在此处找到负责和/或查询的相关代码:https://github.com/balderdashy/sails-mongo/blob/master/lib/query/index.js#L132

我确信sails-mongo根本不支持和/或运算符的嵌套,但我无法找到任何证据。您可以在他们的github页面上提交功能请求。

作为一种解决方法,您可以使用本机底层mongodb适配器来创建查询。作为缺点,您的代码不会与数据库无关。