Home > Mobile >  How can I query all when using Pymongo, group? not using accumulation?
How can I query all when using Pymongo, group? not using accumulation?

Time:12-05

  • 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"
          }
        }
      }
    }
  }
}
  • Related