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

Node.js/Mongoose - Filtering nested documents

本文关键字:过滤 嵌套 文档 Mongoose js Node      更新时间:2023-09-26

长时间的听众第一次调用者:-)

我已经搜索了相当长的时间,但在这里还没有找到问题的答案。 我正在寻找一种方法,或者想知道"正确"的方法,只返回嵌套猫鼬架构中的特定项目。

假设我有这个例子。

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. 对于原始查询,为什么它会返回所有字段而不是我在"位置"语句中指定了什么?

这是典型的行为吗

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

.where("bar.text").equals("Hi"),查询的这一部分称为find()部分。它匹配所有记录,值为 bar.text 作为 Hi

对于原始查询,为什么它会返回所有字段而不是我在"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)
    });});