【问题标题】:Convert ObjectID to String in mongo Aggregation在mongo聚合中将ObjectID转换为字符串
【发布时间】:2016-09-25 00:11:25
【问题描述】:

我现在处于这种情况: 我有一个收藏 X:

{
  _id:ObjectId('56edbb4d5f084a51131dd4c6'),
  userRef:ObjectId('56edbb4d5f084a51131dd4c6'),
  serialNumber:'A123123',
  ...
}

我需要聚合所有文档,按 userRef + serialNumber 对它们进行分组,所以我尝试像这样使用 concat:

$group: {
        _id: {
            '$concat': ['$userRef','-','$serialNumber']
        },
       ...

所以基本上在我在 MongoDB 中的聚合中,我需要通过 ObjectId 和字符串的串联来对文档进行分组。但是,似乎 $concat 只接受字符串作为参数:

uncaught exception: aggregate failed: {

    "errmsg" : "exception: $concat only supports strings, not OID",
    "code" : 16702,
    "ok" : 0
}

有没有办法在聚合表达式中将 ObjectId 转换为 String?

编辑

这个question 是相关的,但我的解决方案不适合我的问题。 (特别是因为我不能在聚合过程中使用 ObjectId.toString())

确实,我在 Mongo 的文档中找不到任何 ObjectId().toString() 操作,但我想知道在这种情况下是否可以做任何棘手的事情。

【问题讨论】:

  • 也许_id: [ $userRef, $serialNumber ] 有效?它不会给你一个字符串。

标签: mongodb mongoose mongodb-query aggregation-framework robo3t


【解决方案1】:

我找不到做我想做的事的方法,所以我创建了一个 MapReduce 函数,最终以我想要的方式生成键(连接其他键)。

最后,它看起来像这样:

db.collection('myCollection').mapReduce(
    function() {
        emit(
            this.userRef.str + '-' + this.serialNumber , {
                count: 1,
                whateverValue1:this.value1,
                whateverValue2:this.value2,
                ...
            }
        )
    },
    function(key, values) {
       var reduce = {}
       .... my reduce function....
        return reduce
    }, {
        query: {
            ...filters_here....
        },
        out: 'name_of_output_collection'
    }
);

【讨论】:

  • 你能告诉我你写的代码是什么吗??
  • @SudhanshuGaur 看看这是否有帮助。我编辑了评论
  • 感谢您的回答实际上我正在阅读有关聚合和 map reduce 的内容,我发现 map reduce 比聚合慢很多倍在聚合中执行此操作。
  • 是的,我知道...但我从未找到使用聚合的解决方案:/
【解决方案2】:

您可以使用$substr https://docs.mongodb.com/manual/reference/operator/aggregation/substr/#exp._S_substr 将任何对象转换为$concat 之前的字符串。

这是对我有用的代码示例。

group_id_i['_id'] = {
    '$concat' => [
        { '$substr' => [ {'$year' => '$t'}, 0, -1] }, '-',
        { '$substr' => [ {'$month' => '$t'}, 0, -1] }, '-',
        { '$substr' => [ {'$dayOfMonth' => '$t'}, 0, -1] }
    ]
} 

t 是 DateTime 字段,这个聚合返回的数据是这样的。

{
    "_id" => "28-9-2016",
    "i" => 2
}

【讨论】:

    【解决方案3】:

    我认为您可以尝试使用包含两个字段的数组来解决它:

    {$project:{newkey:['$userRef','$serialNumber']},{$match:{newkey:{$in:filterArray}}}}
    

    这可能会将具有两个字段的数据匹配到过滤器。请注意,newkey 数组中的数据应与 filterArray 元素具有相同的数据类型。

    【讨论】:

      【解决方案4】:

      现在您可以尝试使用 $toString 聚合,这很简单 将 ObjectId 转换为字符串

      db.collection.aggregate([
          { "$addFields": {
              "userRef": { "$toString": "$userRef" }
          }},
          { "$group": {
            "_id": { "$concat": ["$userRef", "-", "$serialNumber"] }
          }}
      ])
      

      可以查看输出here

      【讨论】:

      • 这是一种新型聚合吗?
      • 不错!我会测试一下!感谢分享!
      • @AndréPerazzi 我也发布了链接...您可以查看...
      • 这可从 MongoDB 版本 4 获得。因此,如果您使用的是较低版本,您将无法执行此操作
      【解决方案5】:

      您可以通过以下方式简单地使用 $toString 在 ObjectID 的聚合中应用 $concat -

      $group: {
          '_id': {
              '$concat': [
                  { '$toString' : '$userRef' },
                  '-',
                  { '$toString' : '$serialNumber'}
              ]
          },
      }
      

      【讨论】:

        猜你喜欢
        • 2017-11-04
        • 1970-01-01
        • 1970-01-01
        • 2016-07-09
        • 2023-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-19
        相关资源
        最近更新 更多