MongoDB 使用 Reduce 进行重复数据删除和排序
MongoDB Dedupe and Sort using Reduce
我正在使用 Reduce
从 array
.
创建 field
的连接 String
例如,假设我有一个 array
的 subdocuments
称为 children
- 每个 child
都有一个 name
field
.
例如
[
{name:"Zak"}, {name:"Bob"}, {name:"Sharon"}, {name:"Zak"}, {name:"Cindy"}, {name:"Bob"}, {name:"Peter"}
]
下面的 expression
会给我一个 "Zak, Bob, Sharon, Zak, Cindy, Bob, Peter, "
;
的“csv”
(是的 - 我知道我可以使用 $cond
来检测最后一次迭代并删除 trail
ing ", "
.
uniqueCsv: {
$reduce: {
input: "$children",
initialValue: '',
in: {
$concat: ["$$this.name", ", ", "$$value"]
}
}
}
是否可以用这个 reduce
dedupe
和 sort
这样我们就可以
"Bob, Cindy, Peter, Sharon, Zak"
?
谢谢!
$setUnion
从 children.name
中获取唯一元素,这将按升序对字符串进行排序
$concat
将第一个参数作为 $$value
传递,第二个作为条件传递,如果值为空,则 return 为空,否则为“,”,第三个作为 $$this
表示当前字符串
db.collection.aggregate([
{
$project: {
uniqueCsv: {
$reduce: {
input: { $setUnion: "$children.name" },
initialValue: "",
in: {
$concat: [
"$$value",
{ $cond: [{ $eq: ["$$value", ""] }, "", ", "] },
"$$this"
]
}
}
}
}
}
])
第二种方法使用 $substr
而不是 $cond
$substr
通过当前reduce操作,reduce操作会return, Bob, Cindy, Peter, Sharon, Zak
- 现在我们只需要从上面的字符串中删除前 2 个字符,第二个参数从第二个位置开始字符串,第三个参数传递字符串长度 -1 将 return 所有字符串
db.collection.aggregate([
{
$project: {
uniqueCsv: {
$substr: [
{
$reduce: {
input: { $setUnion: "$children.name" },
initialValue: "",
in: {
$concat: ["$$value", ", ", "$$this"]
}
}
},
2,
-1
]
}
}
}
])
Warning:
As per MongoDB $setUnion
: The order of the elements in the output array is unspecified.
but as per my experience it return array of string in ascending order, i have used it in my projects as well, i have tested it every way but it gives 100% ascending order.
It is your choice to use this in your project or not without mongodb confirmation.
我正在使用 Reduce
从 array
.
field
的连接 String
例如,假设我有一个 array
的 subdocuments
称为 children
- 每个 child
都有一个 name
field
.
例如
[
{name:"Zak"}, {name:"Bob"}, {name:"Sharon"}, {name:"Zak"}, {name:"Cindy"}, {name:"Bob"}, {name:"Peter"}
]
下面的 expression
会给我一个 "Zak, Bob, Sharon, Zak, Cindy, Bob, Peter, "
;
(是的 - 我知道我可以使用 $cond
来检测最后一次迭代并删除 trail
ing ", "
.
uniqueCsv: {
$reduce: {
input: "$children",
initialValue: '',
in: {
$concat: ["$$this.name", ", ", "$$value"]
}
}
}
是否可以用这个 reduce
dedupe
和 sort
这样我们就可以
"Bob, Cindy, Peter, Sharon, Zak"
?
谢谢!
$setUnion
从children.name
中获取唯一元素,这将按升序对字符串进行排序$concat
将第一个参数作为$$value
传递,第二个作为条件传递,如果值为空,则 return 为空,否则为“,”,第三个作为$$this
表示当前字符串
db.collection.aggregate([
{
$project: {
uniqueCsv: {
$reduce: {
input: { $setUnion: "$children.name" },
initialValue: "",
in: {
$concat: [
"$$value",
{ $cond: [{ $eq: ["$$value", ""] }, "", ", "] },
"$$this"
]
}
}
}
}
}
])
第二种方法使用 $substr
而不是 $cond
$substr
通过当前reduce操作,reduce操作会return, Bob, Cindy, Peter, Sharon, Zak
- 现在我们只需要从上面的字符串中删除前 2 个字符,第二个参数从第二个位置开始字符串,第三个参数传递字符串长度 -1 将 return 所有字符串
db.collection.aggregate([
{
$project: {
uniqueCsv: {
$substr: [
{
$reduce: {
input: { $setUnion: "$children.name" },
initialValue: "",
in: {
$concat: ["$$value", ", ", "$$this"]
}
}
},
2,
-1
]
}
}
}
])
Warning:
As per MongoDB
$setUnion
: The order of the elements in the output array is unspecified.
but as per my experience it return array of string in ascending order, i have used it in my projects as well, i have tested it every way but it gives 100% ascending order.
It is your choice to use this in your project or not without mongodb confirmation.