- I am making a restful api based on flask and Pymongo. Been trying to query data in a specific shape but having a hard time querying it. Below is my query code.
def track_route(from_time, to_time):
doc = myCol.aggregate([
{"$match":{
"MessageTime":{"$gt": from_time},
"MessageTime":{"$lt": to_time}
}},
{"$group":{
"_id":'$MMSI',
"$MMSI":{"accumulator1":"$ROT"}
}},
{"$project":{"_id":0}}
])
doc_list = [i for i in doc]
return doc_list
- It returns this.
pymongo.errors.OperationFailure: The field '$MMSI' must be an accumulator object, full error: {'ok': 0.0, 'errmsg': "The field '$MMSI' must be an accumulator object", 'code': 40234, 'codeName': 'Location40234'}
- This is the shape that I want to return.
[
{
123456789: [
{
MessageTime: '2021-05-28 17:29:22',
BaseStationID: '999999',
MsgType: '11',
mode: '3',
ROT: '0',
SOG: '0.0',
PosAcc: '0',
lon: '99.32404166666667',
lat: '93.47150833333333',
COG: '99.9',
Heading: '68',
MessageTimeU: '1622190562',
},
{
MessageTime: '2021-05-28 17:48:57',
BaseStationID: '4999314',
MsgType: '11',
mode: '1',
ROT: '0',
SOG: '17.7',
PosAcc: '1',
lon: '99.48246666666667',
lat: '9.980546666666667',
COG: '999.0',
Heading: '341',
MessageTimeU: '1622191737',
},
{
MessageTime: '2021-05-28 13:16:50',
BaseStationID: '999914',
MsgType: '11',
mode: '1',
ROT: '-128',
SOG: '0.1',
PosAcc: '1',
lon: '999.531585',
lat: '99.52044166666666',
COG: '998.2',
Heading: '511',
MessageTimeU: '1622175410',
},
{
MessageTime: '2021-05-28 11:45:43',
BaseStationID: '9903702',
MsgType: '11',
mode: '4',
ROT: '0',
SOG: '9.4',
PosAcc: '0',
lon: '99.51709333333334',
lat: '9.952831833333333',
COG: '00.9',
Heading: '511',
MessageTimeU: '1622169943',
},
],
},
{
234567890: [
{
MessageTime: '2021-05-28 20:59:52',
BaseStationID: '000702',
MsgType: '11',
mode: '1',
ROT: '-128',
SOG: '0.0',
PosAcc: '1',
lon: '00.46612166666667',
lat: '00.507135',
COG: '360.0',
Heading: '511',
MessageTimeU: '1622203192',
},
{
MessageTime: '2021-05-28 09:41:51',
BaseStationID: '0003702',
MsgType: '11',
mode: '1',
ROT: '-128',
SOG: '4.5',
PosAcc: '1',
lon: '00.26525833333334',
lat: '00.44930333333333',
COG: '238.7',
Heading: '511',
MessageTimeU: '1622162511',
},
{
MessageTime: '2021-05-28 17:48:50',
BaseStationID: '0003702',
MsgType: '11',
mode: '3',
ROT: '-128',
SOG: '0.0',
PosAcc: '0',
lon: '00.258005',
lat: '00.41504833333333',
COG: '00.4',
Heading: '511',
MessageTimeU: '1622191730',
},
{
MessageTime: '2021-05-28 14:27:42',
BaseStationID: '0003702',
MsgType: '11',
mode: '4',
ROT: '0',
SOG: '7.1',
PosAcc: '1',
lon: '00.260425',
lat: '00.418685',
COG: '65.0',
Heading: '511',
MessageTimeU: '1622179662',
},
],
},
];
- 123456789 and 234567890 are the MMSI value and are the key value for sub documents. How can I query in the shape above? It's nested. If cannot, at least the most similar way.
CodePudding user response:
You have some mistakes in your aggregation, you cannot reference a field as a key, you should put a static field name.
This a correct way to group.
db.collection.aggregate({
"$group": {
"_id": "$MMSI",
"a": { //replace that "a" with any field name you want but not for a $ref
"$push": "$$ROOT" // you need to use an accumulator like $push, and the correct form to reference the whole doc is $$ROOT
}
}
}
Then you can map your info as you wanted. You can test the code here
{
"$replaceRoot": {
"newRoot": {
$arrayToObject: {
$map: {
input: [
"$$ROOT"
],
as: "el",
in: {
"k": {
$toString: "$$el._id"
},
"v": "$$el.a"
}
}
}
}
}
}