简体   繁体   English

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

[英]Node.js/Mongoose - Filtering nested documents

Long time listener first time caller :-) 长时间监听的首次呼叫者:-)

I've searched for a considerable amount of time and haven't quite found an answer to my problem here. 我已经搜索了相当长的时间,但在这里还没有找到解决我的问题的答案。 I'm looking for a way, or would like to know the "proper" way, to only return a specific item within a nested mongoose Schema. 我正在寻找一种方法,或者想知道“正确”的方法,只返回嵌套猫鼬模式中的特定项。

So lets say I have this example. 所以可以说我有这个例子。

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

Result 结果

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

From the query I would've expected it to only return 从查询中,我希望它只会返回

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

So I guess that leads me to a few questions: 所以我想这引出了我几个问题:

  1. Is there a better way this query should be constructed? 有没有更好的方法应构造此查询?
  2. Is this typical behavior and it's up to be to loop over the results and just pull out what I need? 这是典型的行为吗?它只能遍历结果并取出我需要的东西吗?
  3. For the original query, why would it return all fields rather than what I've specified in the 'where' statement? 对于原始查询,为什么它返回所有字段,而不是我在“ where”语句中指定的字段?

Is this typical behavior 这是典型的行为吗

Yes this is how mongodb performs the projection operation. 是的,这是mongodb执行projection操作的方式。

.where("bar.text").equals("Hi") , This part of the query is called the find() part. .where("bar.text").equals("Hi") ,查询的这一部分称为find()部分。 It matches all the records, having the value of bar.text as Hi . 它匹配所有记录,其bar.text的值为Hi

For the original query, why would it return all fields rather than what I've specified in the 'where' statement? 对于原始查询,为什么它返回所有字段,而不是我在“ where”语句中指定的字段?

.select("bar.text") , This is the projection part. .select("bar.text") ,这是projection部分。 Projecting only those fields that we want.This works as expected for fields other than those inside arrays, because at a particular depth, only one unique field would be present. 仅投影我们想要的那些字段。这对于数组内部字段以外的其他字段都可以正常工作,因为在特定深度处,只会出现一个唯一的 field But in the case of arrays, there can be 'n' documents having the same field at the same depth. 但是对于数组,可以有“ n”个文档,它们在相同的深度具有相同的字段。 When an array element is projected, all the sub documents that have this particular field at that level will be shown. 投影数组元素时,将显示在该级别具有此特定字段的所有子文档。 And that makes perfect sense. 这是完全合理的。

and it's up to be to loop over the results and just pull out what I need? 最终要遍历结果并取出我需要的东西吗?

No. There are better ways explained below. 否。下面有更好的解释方法。

Is there a better way this query should be constructed? 有没有更好的方法应构造此查询?

If you are sure that the array contains exactly one document matching the query condition you could make use of the $ (positional projection) operator. 如果您确定该数组仅包含一个与查询条件匹配的文档,则可以使用$ (位置投影)运算符。

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

If you are unsure of how many documents are there in the array with the field value Hi , you could make use of the aggregation operator pipeline as below: 如果不确定数组中字段值为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)
    });});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM