Mongo Aggregation,替换数组内部导致数组具有该内部数组的计数

时间:2017-09-26 10:54:10

标签: mongodb aggregation-framework projection

我正在研究一种社交网络类型的模式,并试图在管道中使用聚合框架来更改文档,以便总结其中的部分内容,特别是用数组大小​​替换数据数组。

例如,鉴于这些原始文档,每个文章都包含一系列帖子,每个帖子都有一系列喜欢的内容:

{ "_id": 1, "posts": [
  {
    "content": "foobar", "likes": [ "11", "12", "13" ]
  }
] }
{ "_id": 2, "posts": [
  {
  "content": "foobar2", "likes": [ "22", "23" ]
  }
] }
{ "_id": 3, "posts": [
  {
  "content": "foobar3", "likes": [ "33" ]
  }
] }

(可直接送入mongoimport

在现实世界中,posts数组中会有许多元素,likes数组中会有更复杂的元素。我需要返回具有相似数量的文档,而不是实际喜欢的文档,例如。

{ _id: 1, posts: [
  { content: 'foobar', likeCount: 3 }
] },
{ _id: 2, posts: [
  { content: 'foobar2', likeCount: 2 }
] },
{ _id: 3, posts: [
  { content: 'foobar3', likeCount: 1 }
] }

$project聚合阶段似乎合适,但我无法得到产品所需的结果。 e.g。

db.getCollection('test').aggregate([
    {
        $project: {
            "posts.likeCount": { $size: "$posts.likes" }
        }
    }
])

给出:

{
    "_id" : 2,
    "posts" : [ 
        {
            "likeCount" : 1
        }
    ]
}
{
    "_id" : 3,
    "posts" : [ 
        {
            "likeCount" : 1
        }
    ]
}
{
    "_id" : 1,
    "posts" : [ 
        {
            "likeCount" : 1
        }
    ]
}

$posts.likes表达式中的$project用法似乎特别关闭,因为$posts是一个数组。

我的输出文档如何包含此内部数组的聚合(计数),同时仍保留原始文档的结构?

我尝试了$unwind$replaceRoot阶段尝试解决方案,但结果却失去了与原始文件相关的特定结构。我一直在阅读MongoDB参考文档,搜索SO和其他地方,但还没有找到解决方案。

2 个答案:

答案 0 :(得分:3)

您可以尝试以下聚合查询。 public class GsonDateDeSerializer implements JsonDeserializer<Date> { ... private SimpleDateFormat format1 = new SimpleDateFormat("MMM dd, yyyy hh:mm:ss a"); private SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss"); ... @Override public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { try { String j = json.getAsJsonPrimitive().getAsString(); return parseDate(j); } catch (ParseException e) { throw new JsonParseException(e.getMessage(), e); } } private Date parseDate(String dateString) throws ParseException { if (dateString != null && dateString.trim().length() > 0) { try { return format1.parse(dateString); } catch (ParseException pe) { return format2.parse(dateString); } } else { return null; } } 要迭代$map数组并使用posts来计算$size的数量。

likes

答案 1 :(得分:1)

如果你需要计算每个内容的喜好,你需要先解开帖子:

db.test.aggregate([
    {$unwind: "$posts"}, 
    {$project: {
        "posts.content" : 1,
        "posts.likeCount": { $size: "$posts.likes" }
    }},
    {$group: {
        _id: "$_id", 
        posts: {$push: "$posts"}
    }}
])