【问题标题】:How to get an 'and' query working with sails-mongodb如何使用sails-mongodb获取“和”查询
【发布时间】:2016-09-03 06:23:59
【问题描述】:

我有一个在 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 和 waterline 是版本“0.12.1”

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

【问题讨论】:

    标签: node.js mongodb express sails.js


    【解决方案1】:

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

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

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

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

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

    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 适配器来创建查询。作为一个缺点,您的代码不会与数据库无关。

    【讨论】:

    • 感谢 artadad。我认为使用本机 mongodb 客户端或sails-mongo 本机底层 mongodb 适配器是要走的路。
    • 为此我最终退回到本机 MongoDB 客户端。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    相关资源
    最近更新 更多