2016-12-17 61 views
0

我有一个具有子文档的父模式。子文档具有与嵌入的对象的阵列的属性:在Mongoose中跳过一个嵌套级别的子文档

儿童模式

var snippetSchema = new Schema({ 
    snippet: [ 
     { 
      language: String, 
      text: String, 
      _id: false 
     } 
    ] 
}); 

父模式

var itemSchema = new Schema({ 
    lsin: Number, 
    identifier: { 
     isbn13: Number, 
    }, 
    title: snippetSchema, 
}); 

其在Item.find返回类似的对象,以便:

[ 
    { 
     _id: (...), 
     lsin: 676765, 
     identifier: { 
      isbn13: 8797734598763 
     }, 
     title: { 
      _id: (...), 
      snippet: [ 
       { 
        language: 'se', 
        text: 'Pippi Långstrump' 
       } 
      ] 
     } 
    } 
] 

我想跳过子文档的一层嵌套当对象被返回给客户端:使用一个getter

function getter() { 
    return this.title.snippet[0]; 
} 

var itemSchema = new Schema({ 
    ... 
    title: { type: snippetSchema, get: getter } 
}); 

#1:

[ 
    { 
     _id: (...), 
     lsin: 676765, 
     identifier: { 
      isbn13: 8797734598763 
     }, 
     title: { 
      language: 'se', 
      text: 'Pippi Långstrump' 
     } 
    } 
] 

到目前为止,我已经尝试

但它创建了一个无限循环导致RangeError: Maximum call stack size exceeded

#2使用虚拟属性

var itemSchema = new Schema({ 
    ..., { 
    toObject: { 
     virtuals: true 
    } 
}); 

itemSchema 
    .virtual('title2') 
    .get(function() { 
     return this.title.snippet[0]; 
}); 

这将产生所期望的嵌套级别,但下一个新的属性,这是不能接受的。据我所知,没有办法覆盖具有虚拟属性的属性。

现在的问题是:有没有其他的方式去获得所需的输出?在整个应用程序中将会有几处对snippetSchema的引用,并且DRY方法是首选。

我是MongoDB和Mongoose的新手。

回答

1

您需要在mongodb聚合管道中使用$project

在我的数据库中,我有以下几点:

> db.items.find().pretty() 
{ 
     "_id" : 123, 
     "lsin" : 676765, 
     "identifier" : { 
       "isbn13" : 8797734598763 
     }, 
     "title" : { 
       "_id" : 456, 
       "snippet" : [ 
         { 
           "language" : "se", 
           "text" : "Pippi Långstrump" 
         } 
       ] 
     } 
} 

然后,我们只需要创建一个简单的汇总查询:

db.items.aggregate([ 
    {$project: { lsin: 1, identifier: 1, title: { $arrayElemAt: [ '$title.snippet', 0 ] }}} 
]) 

这只是使用$项目(https://docs.mongodb.com/v3.2/reference/operator/aggregation/project/)和$ arrayElemAt (https://docs.mongodb.com/v3.2/reference/operator/aggregation/arrayElemAt/)将第一项投影出阵列。如果我们执行,我们将得到以下内容:

{ 
     "_id" : 123, 
     "lsin" : 676765, 
     "identifier" : { 
       "isbn13" : 8797734598763 
     }, 
     "title" : { 
       "language" : "se", 
       "text" : "Pippi Långstrump" 
     } 
} 
+0

干净,简单。没有找到来自Mongoose API的聚合文档的很多文档,这就是为什么我无法找到解决方案,但现在正在阅读MongoDB文档。我应该如何管理数据库写入?宁愿为GET和POST使用相同的JSON。 – unitario

+0

大多数语言驱动程序都将类似的设置复制到标准的JavaScript shell命令中。这是完全正确的,因为你使用不同的JSON来投影你写的东西,当你写回数据库时,你应该考虑使用更新运算符,比如'$ set','$ inc'等等...... –