MongoDB 组聚合多个字段可以推送特定的数组字段?
MongoDB Group aggregation multiple field can push specific array field?
下面是我的mongodb文档
{
"seq": 1,
"cut": [
{
"script":[
{
"type": "a",
"text": "a1"
},
{
"type": "a",
"text": "a2"
},
{
"type": "b",
"text": "b1"
},
{
"type": "c",
"text": "c1"
}
]
},
{
"script":[
{
"type": "d",
"text": "d1"
},
{
"type": "a",
"text": "a3"
},
{
"type": "c",
"text": "c2"
},
{
"type": "b",
"text": "b2"
}
]
}
]
}
我想使用 type 键使用 $unwind
和 $group
进行文档聚合,如下所示。
{
"seq": 1,
"a": ["a1", "a2", "a3"],
"b": ["b1", "b2"],
"c": ["c1", "c2"],
"d": ["d1"]
}
首先,使用$unwind
聚合。
$unwind: {
path: "$cut",
preserveNullAndEmptyArrays: false
}
并且,它的第一个聚合管道结果是:
{
"seq": 1,
"cut": {
"script":[
{
"type": "a",
"text": "a1"
},
{
"type": "a",
"text": "a2"
},
{
"type": "b",
"text": "b1"
},
{
"type": "c",
"text": "c1"
}
]
}
}
{
"seq": 1,
"cut": {
"script":[
{
"type": "d",
"text": "d1"
},
{
"type": "a",
"text": "a3"
},
{
"type": "c",
"text": "c2"
},
{
"type": "b",
"text": "b2"
}
]
}
}
接下来,放松cut.script.
$unwind: {
path: "$cut.script",
preserveNullAndEmptyArrays: false
}
其结果是:
{
"seq": 1,
"cut": {
"script":{
"type": "a",
"text": "a1"
}
}
}
{
"seq": 1,
"cut": {
"script":{
"type": "a",
"text": "a2"
}
}
}
and more 6 document..
最后,我希望此结果与 seq 字段分组。所以我使用 $push
表达式。
{
_id: "$seq",
"a": {
$push: "$cut.script.text"
},
"b": {
$push: "$cut.script.text"
},
"c": {
$push: "$cut.script.text"
},
"d": {
$push: "$cut.script.text"
}
}
但它 $push
表达式是推送脚本的所有项目。
$push
如何使用条件推送特定字段(例如;“type”等于“a”的“text”值)值?
你可以尝试在聚合中使用 $cond
{
$group: {
_id: "$seq",
"a": {
$push: {
$cond: {
if: { $eq: [ "$cut.script.type", "a" ] },
then: ["$cut.script.text"] ,
else: null,
}
}
}
}
}
试试这个 (Mongoplayground Link):
db.collection.aggregate({
$unwind: {
path: "$cut",
preserveNullAndEmptyArrays: false
}
},
{
$unwind: {
path: "$cut.script"
}
},
{
$group: {
"_id": "$seq",
"a": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"a"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
},
"b": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"b"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
},
"c": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"c"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
},
"d": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"d"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
}
}
})
我更喜欢 dynamic/generic 解决方案:
db.collection.aggregate([
{ $unwind: "$cut" },
{ $unwind: "$cut.script" },
{
$group: {
_id: { seq: "$seq", type: "$cut.script.type" },
text: { $push: "$cut.script.text" }
}
},
{ $sort: { "_id.type": 1 } },
{
$group: {
_id: "$_id.seq",
data: { $push: { k: "$_id.type", v: "$text" } }
}
},
{ $replaceWith: { $mergeObjects: [{ seq: "$_id" }, { $arrayToObject: "$data" }] } }
])
下面是我的mongodb文档
{
"seq": 1,
"cut": [
{
"script":[
{
"type": "a",
"text": "a1"
},
{
"type": "a",
"text": "a2"
},
{
"type": "b",
"text": "b1"
},
{
"type": "c",
"text": "c1"
}
]
},
{
"script":[
{
"type": "d",
"text": "d1"
},
{
"type": "a",
"text": "a3"
},
{
"type": "c",
"text": "c2"
},
{
"type": "b",
"text": "b2"
}
]
}
]
}
我想使用 type 键使用 $unwind
和 $group
进行文档聚合,如下所示。
{
"seq": 1,
"a": ["a1", "a2", "a3"],
"b": ["b1", "b2"],
"c": ["c1", "c2"],
"d": ["d1"]
}
首先,使用$unwind
聚合。
$unwind: {
path: "$cut",
preserveNullAndEmptyArrays: false
}
并且,它的第一个聚合管道结果是:
{
"seq": 1,
"cut": {
"script":[
{
"type": "a",
"text": "a1"
},
{
"type": "a",
"text": "a2"
},
{
"type": "b",
"text": "b1"
},
{
"type": "c",
"text": "c1"
}
]
}
}
{
"seq": 1,
"cut": {
"script":[
{
"type": "d",
"text": "d1"
},
{
"type": "a",
"text": "a3"
},
{
"type": "c",
"text": "c2"
},
{
"type": "b",
"text": "b2"
}
]
}
}
接下来,放松cut.script.
$unwind: {
path: "$cut.script",
preserveNullAndEmptyArrays: false
}
其结果是:
{
"seq": 1,
"cut": {
"script":{
"type": "a",
"text": "a1"
}
}
}
{
"seq": 1,
"cut": {
"script":{
"type": "a",
"text": "a2"
}
}
}
and more 6 document..
最后,我希望此结果与 seq 字段分组。所以我使用 $push
表达式。
{
_id: "$seq",
"a": {
$push: "$cut.script.text"
},
"b": {
$push: "$cut.script.text"
},
"c": {
$push: "$cut.script.text"
},
"d": {
$push: "$cut.script.text"
}
}
但它 $push
表达式是推送脚本的所有项目。
$push
如何使用条件推送特定字段(例如;“type”等于“a”的“text”值)值?
你可以尝试在聚合中使用 $cond
{
$group: {
_id: "$seq",
"a": {
$push: {
$cond: {
if: { $eq: [ "$cut.script.type", "a" ] },
then: ["$cut.script.text"] ,
else: null,
}
}
}
}
}
试试这个 (Mongoplayground Link):
db.collection.aggregate({
$unwind: {
path: "$cut",
preserveNullAndEmptyArrays: false
}
},
{
$unwind: {
path: "$cut.script"
}
},
{
$group: {
"_id": "$seq",
"a": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"a"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
},
"b": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"b"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
},
"c": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"c"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
},
"d": {
$push: {
$cond: {
if: {
$eq: [
"$cut.script.type",
"d"
]
},
then: "$cut.script.text",
else: "$$REMOVE"
}
}
}
}
})
我更喜欢 dynamic/generic 解决方案:
db.collection.aggregate([
{ $unwind: "$cut" },
{ $unwind: "$cut.script" },
{
$group: {
_id: { seq: "$seq", type: "$cut.script.type" },
text: { $push: "$cut.script.text" }
}
},
{ $sort: { "_id.type": 1 } },
{
$group: {
_id: "$_id.seq",
data: { $push: { k: "$_id.type", v: "$text" } }
}
},
{ $replaceWith: { $mergeObjects: [{ seq: "$_id" }, { $arrayToObject: "$data" }] } }
])