Node.js / Mongoose - 过滤嵌套文档

时间:2014-11-19 05:09:35

标签: javascript node.js mongodb mongoose

长时间听众第一次来电: - )

我已经搜索了相当多的时间,并且在这里找不到我的问题的答案。我正在寻找一种方式,或者想知道"正确的"方式,仅返回嵌套的mongoose Schema中的特定项。

让我说我有这个例子。

var mongoose = require('mongoose')
var Schema = mongoose.Schema

var conn = mongoose.connect('mongodb://localhost/testjs');

Bar = new Schema({
  text: String
});

Foo = new Schema({
  bar: [Bar]
});

var Foo = mongoose.model('Foo', Foo);

// Clean up the DB
Foo.find({}, function(err, res) {
    for (i in res) {
        res[i].remove()
    }
});

var foo = new Foo()
foo.bar.push({"text":"Hi"})
foo.bar.push({"text":"Bye"})
foo.bar.push({"text":"Hey"})

foo.save(
  function(err){

    var r = Foo
    .where('bar.text').equals('Hi')
    .select('bar.text')
    .exec(function(err, res) {
        console.log(res)
    })
  }
);

结果

[ { _id: 546c235cea0f16dc0d85a60f,
    bar: [ { text: 'Hi' }, { text: 'Bye' }, { text: 'Hey' } ] } ]

从查询中我预计它只会返回

[ { _id: 546c235cea0f16dc0d85a60f,
        bar: [ { text: 'Hi' } ] } ]

所以我想这引出了几个问题:

  1. 是否有更好的方法来构建此查询?
  2. 这是典型的行为吗?它可以循环结果 并拉出我需要的东西?
  3. 对于原始查询,为什么它会返回所有字段而不是 我在'中所指定的内容'声明?

1 个答案:

答案 0 :(得分:1)

  

这是典型行为吗

是的,这是mongodb执行projection操作的方式。

.where("bar.text").equals("Hi"),此部分查询称为find()部分。它匹配所有记录,其值bar.textHi

  

对于原始查询,为什么它会返回所有字段而不是我在'where'语句中指定的字段?

.select("bar.text"),这是projection部分。仅投影我们想要的那些字段。这对于除阵列内部以外的字段的预期工作,因为在特定深度,只有一个唯一 field。但是在数组的情况下,可能存在具有相同深度的相同字段的'n'个文档。投影数组元素时,将显示在该级别具有此特定字段的所有子文档。这很有道理。

  

并且可以循环结果并提取我需要的内容吗?

没有。有更好的方法解释如下。

  

是否有更好的方法来构建此查询?

如果您确定该数组只包含一个与查询条件匹配的文档,则可以使用$(位置投影)运算符。

foo.save(
function(err){
var r = Foo.find({'bar.text':'Hi'},{'bar.$':1},function(err, res) {
    console.log(res)
});});

如果您不确定数组中包含字段值Hi的文档数量,您可以使用聚合运算符管道,如下所示:

  foo.save(
  function(err){
  var r = Foo.aggregate([
  {$match:{"bar.text":"Hi"}},
  {$unwind:"$bar"},
  {$match:{"bar.text":"Hi"}},
  {$group:{"_id":"$_id","bars":{$push:"$bar"}}}
  ],function(err, res) {
        console.log(res)
    });});