选择匹配数组元素并返回选定字段

时间:2017-07-31 07:31:23

标签: javascript node.js mongodb mongoose

我想知道如何为Mongoose查询中匹配的对象数组设置投影。

例如,如果我有一个看起来像这样的Mongoose模型:

var User = new Schema({
  name: String,
  children: [Child]
});

var Child = new Schema({
  name: String,
  height: Number,
  age: Number,
  secret: Number
});

换句话说,可能由此模型产生的示例JSON对象:

User: {
  name: 'abc',
  children: [
    {
      name: 'def',
      height: 123,
      age: 7,
      secret: 2
    },
    {
      name: 'ghi',
      height: 456,
      age: 9,
      secret: 3
    }
  ]
}

如您所见,模型包含属性children,该属性是Child个对象的数组。

如果我仅匹配User中包含children内具有name: 'def'属性的项目的Users.find({ children.name: 'def' })

name

然后,我可以使用位置运算符($)设置投影以选择属性(例如.select({ name: 1, children.$: 1 } )以及匹配对象的属性:

children.$

现在的问题是,通过此预测,Child将始终返回整个secret对象,包括我可能不想查询的属性,例如{ name: 'abc', children: [ { name: 'def', height: 123, age: 7, secret: 2 } ] }

child

理想情况下,我希望能够从通过$获得的name对象中选择某些属性,类似于从父对象User中选择children.$.age的方式,但我找不到办法做到这一点。

选择单个属性的一种方法是使用格式$,但这只能用于选择1个属性,因为多次执行会导致错误,因为您无法使用poisitional {{1} }运算符多次。

.select({
  name: 1,

  // and now select the height and age
  // but only of the child that matches name = 'def'
  // WITHOUT returning the entire object (exclude name and secret)
  children.$.age,
  children.$.height // error
})

在Mongoose中选择由位置操作员获得的对象的投影吗?

1 个答案:

答案 0 :(得分:1)

如果你只想选择一个数组的某些字段来返回那么你正在谈论"重塑"该文件。对于任何超出"基本"字段选择,这意味着使用.aggregate()作为方法,而不是.find()

因此,这里的两个要求是$filter对阵列内容的匹配"匹配"并返回,以及$map返回的实际"字段"来自阵列本身:

User.aggregate([
  { "$match": { "children.name": "def" } },
  { "$project": {
     "name": 1,
     "children": {
       "$map": {
         "input": {
           "$filter": {
             "input": "$children",
             "as": "c",
             "cond": { "$eq": [ "$$c.name", "def" ] } 
           }
         },
         "as": "c",
         "in": {
           "age": "$$c.age",
           "height": "$$c.height"
         }
       }
     }
  }}
])

这里使用$filter是为了将数组的内容减少到仅与条件匹配的内容。是具有与值"name"相同的"def"属性的那些。然后将其作为"input"参数传递给 $map

$map运算符就像它的其他语言对应物一样,它可以重塑数组"根据您在"in"参数中指定的内容返回内容。所以在这里我们实际上只是明确地命名属性并使用当前正在处理的数组元素的变量赋值,以便这些作为" new"数组内容。

整体结果是一个数组,包含:

  1. 只是符合指定条件的项目。
  2. 只是指定要返回的字段。