英文:
MongoDB : - Merge object with same key into one
问题
我正在尝试将数组中具有相同日期但status
键名不同的对象合并到一起。
我有两个集合,users
和canteens
。
我正在尝试获取结果的查询,但无法弄清如何合并具有相同Date
的对象。
输出
User.aggregate([
{ $sort: { workerId: 1 } },
{
$lookup: {
from: "canteens",
localField: "_id",
foreignField: "employeeId",
pipeline: [
{
$match: {
Date: {
$gte: new Date(fromDate),
$lte: new Date(toDate),
},
},
},
{
$project: {
Date: 1,
status: 1,
},
},
],
as: "canteens",
},
},
{
$project: {
_id: 1,
workerId: 1,
workerFirstName: 1,
workerSurname: 1,
workerDepartment: 1,
workerDesignation: 1,
locationName: 1,
canteenData: "$canteens",
},
},
]);
[
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstaname",
"workerSurname": "lastname",
"workerId": "1",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status": "LUNCH",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b2db8db10c24487201e0a2",
"status": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status": "BREAK FAST",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b3d248c076184fb07ff2c4",
"status": "LUNCH",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b42b8ccb57a4cb7af34015",
"status": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
},
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstaname1",
"workerSurname": "lastname1",
"workerId": "2",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status": "LUNCH",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b2db8db10c24487201e0a2",
"status": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status": "BREAK FAST",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b3d248c076184fb07ff2c4",
"status": "LUNCH",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b42b8ccb57a4cb7af34015",
"status": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
}
]
我要尝试的输出
[
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstanem",
"workerSurname": "lastname",
"workerId": "1",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status1": "LUNCH",
"status2": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status1": "BREAK FAST",
"status2": "LUNCH",
"status3": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status1": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
},
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstanem1",
"workerSurname": "lastname1",
"workerId": "2",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status1": "LUNCH",
"status2": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status1
<details>
<summary>英文:</summary>
I am trying to merge an object inside an array with the same date but with a different key name for the `status` key.
I have 2 collections `users` and `canteens`
The query I am trying to get the result but am not able to figure out how to merge the object with the same `Date`
**OUTPUT**
```javascript
User.aggregate([
{ $sort: { workerId: 1 } },
{
$lookup: {
from: "canteens",
localField: "_id",
foreignField: "employeeId",
pipeline: [
{
$match: {
Date: {
$gte: new Date(fromDate),
$lte: new Date(toDate),
},
},
},
{
$project: {
Date: 1,
status: 1,
},
},
],
as: "canteens",
},
},
{
$project: {
_id: 1,
workerId: 1,
workerFirstName: 1,
workerSurname: 1,
workerDepartment: 1,
workerDesignation: 1,
locationName: 1,
canteenData: "$canteens",
},
},
]);
[
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstaname",
"workerSurname": "lastname",
"workerId": "1",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status": "LUNCH",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b2db8db10c24487201e0a2",
"status": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status": "BREAK FAST",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b3d248c076184fb07ff2c4",
"status": "LUNCH",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b42b8ccb57a4cb7af34015",
"status": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
},
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstaname1",
"workerSurname": "lastname1",
"workerId": "2",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status": "LUNCH",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b2db8db10c24487201e0a2",
"status": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status": "BREAK FAST",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b3d248c076184fb07ff2c4",
"status": "LUNCH",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b42b8ccb57a4cb7af34015",
"status": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
}
]
The output I am trying to get
[
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstanem",
"workerSurname": "lastname",
"workerId": "1",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status1": "LUNCH",
"status2": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status1": "BREAK FAST",
"status2": "LUNCH",
"status3": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status1": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
},
{
"_id": "60e6fd3616dd663e84a925e2",
"workerFirstName": "Firstanem1",
"workerSurname": "lastname1",
"workerId": "2",
"locationName": "location",
"workerDesignation": "designation",
"workerDepartment": "department",
"canteenData": [
{
"_id": "63b285b9e92eee614feb7be1",
"status1": "LUNCH",
"status2": "DINNER",
"Date": "2023-01-02T00:00:00.000Z"
},
{
"_id": "63b39b247adbeb50bfbe3503",
"status1": "BREAK FAST",
"status2": "LUNCH",
"status3": "DINNER",
"Date": "2023-01-03T00:00:00.000Z"
},
{
"_id": "63b4ef71e038498fe6634506",
"status1": "BREAK FAST",
"Date": "2023-01-04T00:00:00.000Z"
}
]
}
]
答案1
得分: 1
一个选项是在您的$lookup
管道聚合中添加2个步骤:
{
"$group": {
"_id": "$Date",
"_idVal": { "$first": "$_id" },
"data": { "$addToSet": "$status" }
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ "_id": "$_idVal", "Date": "$_id" },
{
"$arrayToObject": {
"$reduce": {
"input": "$data",
"initialValue": [],
"in": {
"$concatArrays": [
"$$value",
[
{
"k": {
"$concat": [
"status",
{
"$toString": {
"$add": [
{ "$size": "$$value" },
1
]
}
}
]
},
"v": "$$this"
}
]
]
}
}
}
}
]
}
}
}
在playground示例上查看它的运行方式。
英文:
One option is to add 2 steps into your $lookup
pipeline aggregation:
{$group: {
_id: "$Date",
_idVal: {$first: "$_id"},
data: {$addToSet: "$status"}
}},
{$replaceRoot: {
newRoot: {
$mergeObjects: [
{_id: "$_idVal", Date: "$_id"},
{$arrayToObject: {
$reduce: {
input: "$data",
initialValue: [],
in: {$concatArrays: [
"$$value",
[{k: {$concat: [
"status",
{$toString: {$add: [{$size: "$$value"}, 1]}}
]},
v: "$$this"}]
]}
}
}}
]
}
}}
See how it works on the playground example
答案2
得分: 0
不容易动态创建status1
,status2
,...变量,我们如何知道BREAK FAST
应该是status1
而不是status2
。
替代解决方案: 我们在相关子查询内使用$group
,将所有status
值推送到一个array
中。
db.users.aggregate([
{
"$lookup": {
"from": "canteens",
"localField": "_id",
"foreignField": "employeeId",
"pipeline": [
{
// 在此处放置您的自定义过滤器
$match: {}
},
{
$group: {
_id: "$Date",
// 选择“first” canteens _id
id: {
$first: "$_id"
},
status: {
$push: "$status"
}
}
},
{
$project: {
_id: "$id",
Date: "$_id",
status: 1
}
},
],
"as": "canteenData",
}
}
])
英文:
It's not easy to create status1
, status2
, ...
variables dynamically + how do we know BREAK FAST
should be status1
and not status2
.
Alternative solution: We $group
inside correlated subqueries and push all status
values into an array
db.users.aggregate([
{
"$lookup": {
"from": "canteens",
"localField": "_id",
"foreignField": "employeeId",
pipeline: [
{
// Put your custom filters here
$match: {}
},
{
$group: {
_id: "$Date",
//pick "first" canteens _id
id: {
$first: "$_id"
},
status: {
$push: "$status"
}
}
},
{
$project: {
_id: "$id",
Date: "$_id",
status: 1
}
},
],
as: "canteenData",
}
}
])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论