合并来自多个MongoDB文档的数组

时间:2018-05-25 23:17:13

标签: mongodb mongoose

我正在尝试编写一些查询,其中包含有关YouTubers及其视频的文档,然后按时间顺序返回所有视频的单个列表。

到目前为止我的查询(在Mongoose中):

public OAuth2AccessToken getAccessToken() throws HttpRequestMethodNotSupportedException {
    HashMap<String, String> parameters = new HashMap<>();
    parameters.put("client_id", CLIENT_ID);
    parameters.put("client_secret", CLIENT_SECRET);
    parameters.put("grant_type", "client_credentials");

    ClientDetails clientDetails = clientDetailsStore.get(CLIENT_ID);

    // Create principal and auth token
    User userPrincipal = new User(CLIENT_ID, CLIENT_SECRET, true, true, true, true, clientDetails.getAuthorities());

    UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(userPrincipal, CLIENT_SECRET,
            clientDetails.getAuthorities());

    ResponseEntity<OAuth2AccessToken> accessToken = tokenEndpoint.postAccessToken(principal, parameters);

    return accessToken.getBody();
}

我得到了这些结果:

return mongoose.model('creators').find({
  id: {}
})

理想情况下,我想做的是返回以下内容:

[
    {
        "_id": "5b0891a3dcec4912601e32ce",
        "name": "CaptainDisillusion",
        "id": "UCEOXxzW2vU0P-0THehuIIeg",
        "videos": [
            {
                "_id": "5b0891a3dcec4912601e32cf",
                "name": "Quick D: A Fighter Jet Says Hi",
                "id": "-NPmBkYb_mY",
                "date": "2018-05-10T16:30:30.000Z"
            }
        ],
        "__v": 0
    },
    {
        "_id": "5b08967b66d8321034176afb",
        "name": "Curious Droid",
        "id": "UC726J5A0LLFRxQ0SZqr2mYQ",
        "videos": [
            {
                "_id": "5b0891a3dcec4912601e32cf",
                "name": "Guest post bloggers wanted for the Curious Droid website",
                "id": "sNLvdoValBw",
                "date": "2018-05-23T16:30:30.000Z"
            }
        ],
        "__v": 0
    }
]

仅返回所有文档的一个数组,并以最新的顺序返回。

这可能吗?如果可以,我该怎么做呢?

谢谢!

2 个答案:

答案 0 :(得分:2)

您需要aggregate()。您可以使用$unwind$replaceRoot

return mongoose.model('creators').aggregate([
  // { "$match": { ... } },                      // A real condition to match the document
  { "$unwind": "$videos" },
  { "$replaceRoot": { "newRoot": "$videoes" } }
])

或明确使用$project所有字段:

return mongoose.model('creators').aggregate([
  // { "$match": { ... } },                      // A real condition to match the document
  { "$unwind": "$videos" },
  { "$project": {
     "_id": "$videos._id",
     "name": "$videos.name",
     "id": "$videos.id",
     "date": "$videos.date"
  }}
])

这些是将嵌入式阵列内容推广到顶级&#34;输出中的文件。

注意:对于文档或数组内容的任何查询条件都应该在&#34; $unwind之前完成&#34;这意味着将$match有效用于查询条件,并可能首先对数组内容应用$filter投影。如果你不做那些&#34;首先&#34;您正在为您的应用程序创建不必要的开销。

无论如何,使用$unwind的整个过程非常昂贵。如果实际上值得保留文档嵌入或者您的查询确实更适合将文档放在单独的集合中,那么实际上要仔细查看您的查询模式并真正做出决定会更明智。

答案 1 :(得分:1)

您需要使用$unwind来平展数组项目,然后将内部$videos作为新的根项目与$sort一起推广,以便为您的视频项目订购。

db.tests.aggregate([
      {$match: ...},
      {$unwind: "$videos"}, 
      {$replaceRoot: {newRoot: "$videos"}}, 
      {$sort: {date: -1}} // Newest first
])