Reputation: 158
I have an existing collection with documents similar to below
{
"_id" : UUID("ef2f3778-c74a-4a40-9169-a7798bc6c776"),
"feedId" : UUID("677d0a5a-0ceb-43d9-954d-bfefddc22ca2"),
"events" : {
"1500" : {
"t" : ISODate("2020-08-20T02:25:00.000Z"),
"a" : {
"Manager" : "Joe",
"Amount" : 20.3
}
},
"1800" : {
"t" : ISODate("2020-08-20T02:30:00.000Z"),
"a" : {
"Manager" : "Joe",
"Amount" : 21.3
}
},
"2100" : {
"t" : ISODate("2020-08-20T02:35:00.000Z"),
"a" : {
"Manager" : "Joe",
"Amount" : 22.3
}
},
"2400" : {
"t" : ISODate("2020-08-20T02:40:00.000Z"),
"a" : {
"Manager" : "Joe",
"Amount" : 23.3
}
}
}
}
I am interested in a query that returns all the Amount field values ordered in time (the "t" field). Now, I recognize the "events" embedded document is not structured properly most likely. It should be an array. But this is the hand dealt I am afraid, i.e. don't have an option to change the documents. How do I get a query that returns something akin to [20.3, 21.3, 22.3, 23.3, etc.] from all the objects in the collection with the same feedId?
Edit: I'll add that the event objects/documents don't have a uniform name across each collection object. I.e. here you see 1500, 1800, 2100, etc. this document but the next document may have 1500, and 3000 only.
Reference to another post who had the same question but hit a wall it seems (without changing the document schema to arrays):
MongoDB Query Embedded Document Field
Upvotes: 0
Views: 496
Reputation: 158
@J.F's answer got me close. Here is the query that worked for me:
db.collection.aggregate(
[
{ $match: { feedId: 2 } },
{ $project: { events: {$objectToArray: "$events"} } },
{
"$unwind": "$events"
},
{
"$sort": {
"events.v.t": 1
}
},
{ $group: { "_id": null, Amounts: { $push: "$events.v.a.Amount" } } },
{
"$project": {
"Amounts": 1,
"_id": 0
}
}
]
)
It's producing the expected result for me. I hope it's correct.
Result:
/* 1 */
{
"Amounts" : [
20.3,
21.3,
22.3,
23.3,
24.3,
25.3,
26.3,
27.3,
28.3,
29.3,
30.3,
31.3,
32.3,
33.3,
34.3,
35.3,
36.3,
...
Upvotes: 1
Reputation: 15177
Try this query and check if it is the behaviour you expect (example here)
Note that I've change dates for number to read easier.
db.collection.aggregate([
{
"$match": {
"feedId": 2
}
},
{
"$project": {
"events": {
"$objectToArray": "$events"
}
}
},
{
"$unwind": "$events"
},
{
"$sort": {
"events.v.t": 1
}
},
{
"$group": {
"_id": "$_id",
"events": {
"$push": "$events"
}
}
},
{
"$addFields": {
"count": "$events.v.a.Amount"
}
},
{
"$project": {
"count": 1,
"_id": 0
}
}
])
First $match
the feedId
field, then is necessary use $objectToArray
since your schema is compound by key-values objects.
Then $unwind
to can do the $sort
and regroup again.
After that I've added a new field count
that contains the total amount and I've used $project
to shor only this field.
Upvotes: 1