简体   繁体   中英

How to filter document by a value in the dictionary in arangodb?

I have following structure in arangodb collection named clientShadow .

{
  "_class": "com.syncservice.document.ClientShadow",
  "sessions": {
  "session-id-2": {
      "workspaceId": "workspace-id-1",
      "message": {
        "lastSynced": 0,
        "lastAvailable": 1674630705773
      }
    },
    "session-id-1": {
      "workspaceId": "workspace-id-1",
      "message": {
        "lastSynced": 0,
        "lastAvailable": 1674630705773
      }
    },
    "session-id-0": {
      "workspaceId": "workspace-id-1",
      "message": {
        "lastSynced": 0,
        "lastAvailable": 1674630705773
      }
    }
  },
  "synced": true
}

Here sessions is a map/dictionary of session_id as string and session object as value.

I want to fetch all the sessions from collection where session's lastSynced and lastAvailable aren't same.

I tried following query

FOR doc IN clientShadow
  FOR session IN doc['sessions']
    FILTER session.message.lastSynced != session.message.lastAvailable
    RETURN {'session': session}

But I found out that FOR IN works with collections and gives me following error

Query: AQL: collection or array expected as operand to FOR loop; you provided a value of type 'object' (while executing)

To retain the original data and query structure, don't use ATTRIBUTES , use VALUES :

FOR doc IN clientShadow
  FOR session IN VALUES(doc['sessions'])
    FILTER session.message.lastSynced != session.message.lastAvailable
    RETURN {'session': session}

If you cannot change the data structure, you can use ATTRIBUTES to access the sessions as array:

Edit: Code as fixed by Kshiti Kshitij Dhakal (Attributes returns a list of the names of the attributes)

FOR doc IN clientShadow 
  FOR session IN ATTRIBUTES(doc['sessions']) 
    FILTER 
      doc.sessions[session].message.lastSynced 
        != doc.sessions[session].message.lastAvailable 
    RETURN {'session': doc.sessions[session]}

Old (wrong) suggestion:

FOR doc IN clientShadow
  FOR session IN ATTRIBUTES(doc['sessions'])
    FILTER session.message.lastSynced != session.message.lastAvailable
    RETURN {'session': session}

If you can change the data structure, don't use an object for sessions, but a list:

{
  "_class": "com.syncservice.document.ClientShadow",
  "sessions": [
    {
      "sessionId": "session-id-2",
      "workspaceId": "workspace-id-1",
      "message": {
        "lastSynced": 0,
        "lastAvailable": 1674630705773
      }
    },
    ...
  ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM