繁体   English   中英

在 MongoDB 的单个字段中连接数组中的字符串值

[英]Concatenate string values in array in a single field in MongoDB

假设我有一系列格式如下的文档:

{
    "_id": "3_0",
    "values": ["1", "2"]
}

我想获得连接在单个字段中的数组值的投影:

{
    "_id": "3_0",
    "values": "1_2"
}

这可能吗? 我试过$concat但我想我不能使用$values作为$concat的数组。

在现代 MongoDB 版本中,您可以。 您仍然不能“直接”将数组应用于$concat ,但是您可以使用$reduce来处理数组元素并生成以下内容:

db.collection.aggregate([
  { "$addFields": {
    "values": { 
      "$reduce": {
        "input": "$values",
        "initialValue": "",
        "in": {
          "$cond": {
            "if": { "$eq": [ { "$indexOfArray": [ "$values", "$$this" ] }, 0 ] },
            "then": { "$concat": [ "$$value", "$$this" ] },
            "else": { "$concat": [ "$$value", "_", "$$this" ] }
          }    
        }
      }        
    }
  }}
])

当然与$indexOfArray结合,以便在它是数组的“第一个”索引时"_"下划线“连接”。

我的额外“愿望”也得到了$sum回答:

db.collection.aggregate([
  { "$addFields": {
    "total": { "$sum": "$items.value" }
  }}
])

一般情况下,这种类型的聚合运算符会增加一些项目数组。 这里的区别在于它意味着编码表示中提供的“参数”的“数组”,与当前文档中存在的“数组元素”相反。

您真正可以在文档中存在的数组中进行项目串联的唯一方法是执行某种 JavaScript 选项,就像mapReduce 中的这个示例一样

db.collection.mapReduce(
    function() {
        emit( this._id, { "values": this.values.join("_") } );
    },
    function() {},
    { "out": { "inline": 1 } }
)

当然,如果您实际上没有聚合任何东西,那么最好的方法可能是在您的客户端代码中简单地执行“连接”操作,以对查询结果进行后处理。 但是如果它需要跨文档用于某些目的,那么 mapReduce 将是唯一可以使用它的地方。


我可以添加“例如”我喜欢这样的工作:

{
    "items": [
        { "product": "A", "value": 1 },
        { "product": "B", "value": 2 },
        { "product": "C", "value": 3 }
    ]
}

总的来说:

db.collection.aggregate([
    { "$project": {
        "total": { "$add": [
            { "$map": {
                "input": "$items",
                "as": "i",
                "in": "$$i.value"
            }}
        ]}
    }}
])

但它不能那样工作,因为$add需要参数而不是文档中的数组。 叹! :(。对此的“按设计”推理的一部分可能会被争论为“仅仅因为”它是从转换结果传入的奇异值的数组或“列表”,因此不能“保证”这些是实际上是操作员期望的“有效”奇异数值类型值。至少不是在当前实现的“类型检查”方法中。

这意味着现在我们仍然必须这样做:

db.collection.aggregate([
   { "$unwind": "$items" },
   { "$group": {
       "_id": "$_id",
        "total": { "$sum": "$items.value" }
   }}
])

而且遗憾的是,也无法应用这样的分组运算符来连接字符串。

因此,您可以希望对此进行某种更改,或者希望进行某种更改以允许在$map操作的范围内以某种方式更改外部作用域变量。 更好的是,新的$join操作也将受到欢迎。 但是这些在写作时并不存在,并且可能在未来一段时间内不会存在。

您可以将reduce运算符与substr运算符一起使用。

db.collection.aggregate([
{
    $project: {
        values: {
            $reduce: {
              input: '$values',
              initialValue: '',
              in: {
                $concat: ['$$value', '_', '$$this']
              }
            }
        }   
    }       
},
{
    $project: {
        values: { $substr: ['$values', 1 , -1]}
    }       
}])

Mongo 4.4开始, $function聚合运算符允许应用自定义 javascript 函数来实现 MongoDB 查询语言不支持的行为。

例如,为了连接字符串数组:

// { "_id" : "3_0", "values" : [ "1", "2" ] }
db.collection.aggregate(
  { $set:
    { "values":
      { $function: {
          body: function(values) { return values.join('_'); },
          args: ["$values"],
          lang: "js"
      }}
    }
  }
)
// { "_id" : "3_0", "values" : "1_2" }

$function有 3 个参数:

  • body ,这是要应用的函数,其参数是要加入的数组。
  • args ,其中包含body函数作为参数的记录字段。 在我们的例子中"$values"
  • lang ,这是编写body函数的语言。 目前只有js可用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM