在 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 版本中可以。您仍然无法 "directly" 将数组应用于 $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" ] }
}
}
}
}
}}
])
为了不"concatenate"与"_"
下划线结合$indexOfArray
当然是"first"数组的索引。
我的附加 "wish" 也得到了 $sum
的回答:
db.collection.aggregate([
{ "$addFields": {
"total": { "$sum": "$items.value" }
}}
])
这种情况通常会在采用项目数组的聚合运算符中出现。这里的区别在于它意味着编码表示中提供的 "array" of "aguments" 与当前文档中存在的 "array element" 相反。
唯一可以真正将文档中数组中的项目串联起来的方法是使用某种 JavaScript 选项,如 mapReduce 中的示例:
db.collection.mapReduce(
function() {
emit( this._id, { "values": this.values.join("_") } );
},
function() {},
{ "out": { "inline": 1 } }
)
当然,如果您实际上没有聚合任何东西,那么最好的方法可能是在 post 处理查询结果时在客户端代码中简单地执行 "join" 操作。但是如果它需要跨文档用于某些目的,那么 mapReduce 将是唯一可以使用它的地方。
我可以补充一点 "for example" 我希望这样的东西能起作用:
{
"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
需要参数而不是文档中的数组。叹! :(。"by design" 的部分推理可能会争辩说 "just because" 它是一个数组或 "list" 从转换结果传入的奇异值它不是 "guaranteed" 这些实际上是运算符期望的 "valid" 单数值类型值。至少在 "type checking".
当前实现的方法中不是
这意味着现在我们仍然需要这样做:
db.collection.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": "$_id",
"total": { "$sum": "$items.value" }
}}
])
同样遗憾的是,也没有办法应用这样的分组运算符来连接字符串。
因此,您可以希望对此进行某种更改,或者希望进行一些更改,允许以某种方式在 $map
操作范围内更改外部范围的变量。更好的是,也欢迎新的 $join
操作。但这些在撰写本文时并不存在,并且可能在未来一段时间内不会存在。
您可以使用 reduce operator together with the 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
个可用。
假设我有一系列格式如下的文档:
{
"_id": "3_0",
"values": ["1", "2"]
}
并且我想获得串联在单个字段中的数组值的投影:
{
"_id": "3_0",
"values": "1_2"
}
这可能吗?我试过 $concat
但我想我不能使用 $values
作为 $concat
.
在现代 MongoDB 版本中可以。您仍然无法 "directly" 将数组应用于 $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" ] }
}
}
}
}
}}
])
为了不"concatenate"与"_"
下划线结合$indexOfArray
当然是"first"数组的索引。
我的附加 "wish" 也得到了 $sum
的回答:
db.collection.aggregate([
{ "$addFields": {
"total": { "$sum": "$items.value" }
}}
])
这种情况通常会在采用项目数组的聚合运算符中出现。这里的区别在于它意味着编码表示中提供的 "array" of "aguments" 与当前文档中存在的 "array element" 相反。
唯一可以真正将文档中数组中的项目串联起来的方法是使用某种 JavaScript 选项,如 mapReduce 中的示例:
db.collection.mapReduce(
function() {
emit( this._id, { "values": this.values.join("_") } );
},
function() {},
{ "out": { "inline": 1 } }
)
当然,如果您实际上没有聚合任何东西,那么最好的方法可能是在 post 处理查询结果时在客户端代码中简单地执行 "join" 操作。但是如果它需要跨文档用于某些目的,那么 mapReduce 将是唯一可以使用它的地方。
我可以补充一点 "for example" 我希望这样的东西能起作用:
{
"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
需要参数而不是文档中的数组。叹! :(。"by design" 的部分推理可能会争辩说 "just because" 它是一个数组或 "list" 从转换结果传入的奇异值它不是 "guaranteed" 这些实际上是运算符期望的 "valid" 单数值类型值。至少在 "type checking".
这意味着现在我们仍然需要这样做:
db.collection.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": "$_id",
"total": { "$sum": "$items.value" }
}}
])
同样遗憾的是,也没有办法应用这样的分组运算符来连接字符串。
因此,您可以希望对此进行某种更改,或者希望进行一些更改,允许以某种方式在 $map
操作范围内更改外部范围的变量。更好的是,也欢迎新的 $join
操作。但这些在撰写本文时并不存在,并且可能在未来一段时间内不会存在。
您可以使用 reduce operator together with the 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
个可用。