param trivedi
param trivedi

Reputation: 171

Query AQL syntax required for following JSON structure

I have a JSON structure like this

{
  "Items": {
     "Apple": {
       "Type": 2,
       "keyVal": "6044e3a3-c064-4171-927c-2440e2f65660"
     },
     "Lemons": {
       "Type": 1,
       "keyVal": "79c45f4d-4f62-4c8e-8de1-79e04fc9b95d"
     }
  },
  "Species": 0,
  "Name": "Test Fruit",
  "Description": "Test Des",
  "Creator": "xyz",
  "SKey" : "123"
}

This is present in a collection named Fruits.

Query: I am trying to write and AQL query to find the SKey where KeyVal value in Items is some value.

I am traditionally used to the SQL syntax but this is the first time I am venturing into the AQL(Arango DB).

Any help with the Syntax is appretiated

Upvotes: 0

Views: 267

Answers (1)

Kaveh Vahedipour
Kaveh Vahedipour

Reputation: 3477

The basics of AQL are explained here really well: https://docs.arangodb.com/3.11/aql/

FOR item IN Items FILTER item.keyVal == "someValue" RETURN item

Would be your minimal SQL SELECT ... WHERE statement.

BTW: There is a comparative introduction to be found here:
https://arangodb.com/why-arangodb/sql-aql-comparison/

A good way to learn AQL is to try small pieces of code an return the result for inspection, to gradually create more complex queries.

For example, let's return one of the nested keyVal values:

FOR doc IN Fruits
  RETURN doc.Items.Apple.keyVal
  // "6044e3a3-c064-4171-927c-2440e2f65660"

To filter by Apple keyVal and return SKey, you can do:

FOR doc IN Fruits
  FILTER doc.Items.Apple.keyVal == "6044e3a3-c064-4171-927c-2440e2f65660"
  RETURN doc.SKey
  // "123"

You can return both keyVal values too:

FOR doc IN Fruits
  RETURN [
    doc.Items.Apple.keyVal,
    doc.Items.Lemons.keyVal
  ]
  // [
  //   "6044e3a3-c064-4171-927c-2440e2f65660",
  //   "79c45f4d-4f62-4c8e-8de1-79e04fc9b95d"
  // ]

To return SKey if either is equal to some value, try this:

FOR doc IN Fruits
  FILTER "79c45f4d-4f62-4c8e-8de1-79e04fc9b95d" IN [
    doc.Items.Apple.keyVal,
    doc.Items.Lemons.keyVal
  ]
  RETURN doc.SKey

Note: IN is used here as array operator, like is {value} contained in {array}.

To return all keyVal values hardcoding the attribute paths, you can make use of the ATTRIBUTES() AQL function:

FOR doc IN Fruits
  FOR attr IN ATTRIBUTES(doc.Items)
    RETURN doc.Items[attr].keyVal

To return SKey if any of the nested keyVal values match, we can do:

FOR doc IN Fruits
  LET keyVals = (FOR attr IN ATTRIBUTES(doc.Items)
    RETURN doc.Items[attr].keyVal
  )
  FILTER "6044e3a3-c064-4171-927c-2440e2f65660" IN keyVals
  RETURN doc.SKey

Note: this uses a subquery to capture the intermediate result.

To test if all specified values are contained, you could do:

LET ids = [
  "79c45f4d-4f62-4c8e-8de1-79e04fc9b95d",
  "6044e3a3-c064-4171-927c-2440e2f65660"
]
FOR doc IN Fruits
  LET keyVals = (FOR attr IN ATTRIBUTES(doc.Items)
    RETURN doc.Items[attr].keyVal
  )
  FILTER ids ALL IN keyVals
  RETURN doc.SKey

ALL IN is an array comparison operator.

Note that it would require a change to your data model if you wanted to use indexes without hardcoding the attributes paths, and also different queries.

Upvotes: 2

Related Questions