有条件地减少Mongo Aggregation中的两个数组字段

我有一个如下所示的集合:

{
  "_id": 1,
  "user": "xyz",
  "sentence": "I watch movies and web series.",
  "nouns": [
    "movies",
    "web series"
  ],
  "verbs": [
    "watch"
  ]
},
{
  "_id": 2,
  "user": "xyz",
  "sentence": "movies are good way to relax",
  "nouns": [
    "movies"
  ],
  "verbs": [
    "relax"
  ]
}

There are two array fields, nouns and verbs for each user's sentences. I want to group the documents by user field and separately count the number of each distinct elements in nouns and verbs arrays. I have tried the following query (if you wan't you can skip to the last stage of this aggregation):

db.collection.aggregate([
  {
    $group: {
      _id: "$user",
      sentence: {
        $push: "$sentence"
      },
      verbs: {
        $push: "$verbs"
      },
      nouns: {
        $push: "$nouns"
      }
    }
  },
  {
    $project: {
      verbs: {
        $reduce: {
          input: "$verbs",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              "$$this"
            ]
          }
        }
      },
      nouns: {
        $reduce: {
          input: "$nouns",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              "$$this"
            ]
          }
        }
      },
      sentence: 1
    }
  },
  {
    $project: {
      nouns_count_temp: {
        $map: {
          input: "$nouns",
          as: "c",
          in: {
            k: "$$c",
            v: 1
          }
        }
      },
      verbs_count_temp: {
        $map: {
          input: "$verbs",
          as: "c",
          in: {
            k: "$$c",
            v: 1
          }
        }
      },
      sentence: 1
    }
  },
  {
    $project: {
      sentence: 1,
      noun_count: {
        $reduce: {
          input: "$nouns_count_temp",
          initialValue: [],
          in: {
            $cond: [
              {
                $in: [
                  {
                    k: "$$this.k",
                    v: "$$this.v"
                  },
                  "$$value"
                ]
              },
              {
                $add: [
                  "$$value.$.v",
                  1
                ]
              },
              {
                $concatArrays: [
                  "$$value",
                  [
                    {
                      k: "$$this.k",
                      v: "$$this.v"
                    }
                  ]
                ]
              }
            ]
          }
        }
      },
      verb_count: {
        $reduce: {
          input: "$verbs_count_temp",
          initialValue: [],
          in: {
            $cond: [
              {
                $in: [
                  {
                    k: "$$this.k",
                    v: "$$this.v"
                  },
                  "$$value"
                ]
              },
              {
                $add: [
                  "$$value.$.v",
                  1
                ]
              },
              {
                $concatArrays: [
                  "$$value",
                  [
                    {
                      k: "$$this.k",
                      v: "$$this.v"
                    }
                  ]
                ]
              }
            ]
          }
        }
      }
    }
  }
])

I am facing problem in the last state of the aggregation. I want to know, if there is any better way to use $cond in $reduce, so that I can conditionally reduce the arrays.

我的预期输出如下:

{
  "_id": "xyz",
  "noun_count": {
    "movies": 2,
    "web series": 1
  },
  "sentence": [
    "I watch movies and web series.",
    "movies are good way to relax"
  ],
  "verb_count": {
    "relax": 1,
    "watch": 1
  }
}

Here is the MongoPlayGroundLink, that I have tried.

评论
乐然
乐然

我知道它的结构有些不同,但是看看下面的输出对您有用吗?我对汇总了解不多,但我认为这可能对您有所帮助。 :)

{
  "_id": "xyz",
  "nouns": [
    {"value": "movies", "count": 2},
    {"value": "web series", "count": 1}
  ],
  "sentence": [
    "I watch movies and web series.",
    "movies are good way to relax"
  ],
  "verb_count": [
    {"value": "relax", "count": 1},
    {"value": "watch", "count": 1}
  ]
}

Playground link - https://mongoplayground.net/p/hzo0ooQQTT2

我使用的查询:

db.collection.aggregate([
  {
    $group: {
      _id: "$user",
      sentence: {
        $push: "$sentence"
      },
      verbs: {
        $push: "$verbs"
      },
      nouns: {
        $push: "$nouns"
      }
    }
  },
  {
    $project: {
      verbs: {
        $reduce: {
          input: "$verbs",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              "$$this"
            ]
          }
        }
      },
      nouns: {
        $reduce: {
          input: "$nouns",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              "$$this"
            ]
          }
        }
      },
      sentence: 1
    }
  },
  {
    "$unwind": "$nouns"
  },
  {
    "$group": {
      "_id": {
        "_id": "$_id",
        "noun": "$nouns"
      },
      "sentence": {
        "$first": "$sentence"
      },
      "key": {
        "$first": "$_id"
      },
      "verbs": {
        "$first": "$verbs"
      },
      "count": {
        "$sum": 1
      }
    }
  },
  {
    "$group": {
      "_id": "$key",
      "sentence": {
        "$first": "$sentence"
      },
      "verbs": {
        "$first": "$verbs"
      },
      "nouns": {
        $push: {
          value: "$_id.noun",
          count: "$count"
        }
      }
    }
  },
  {
    "$unwind": "$verbs"
  },
  {
    "$group": {
      "_id": {
        "_id": "$_id",
        "verb": "$verbs"
      },
      "sentence": {
        "$first": "$sentence"
      },
      "key": {
        "$first": "$_id"
      },
      "nouns": {
        "$first": "$nouns"
      },
      "count": {
        "$sum": 1
      }
    }
  },
  {
    "$group": {
      "_id": "$key",
      "sentence": {
        "$first": "$sentence"
      },
      "nouns": {
        "$first": "$nouns"
      },
      "verbs": {
        $push: {
          value: "$_id.verb",
          count: "$count"
        }
      }
    }
  }
])
点赞
评论