arangodb

Not able to use for loop in ternary operator in arangodb


How do we write conditions in arango, that includes for loops. I can elaborate the requirement below.

My requirement is if a particular attribute(array type) exists in the arango collection, i would read data from the collection(that requires a loop) or else, might do the following :

  1. return null
  2. return empty string ""
  3. do nothing.

Is this possible to achieve in arango?

The helping methods could be -->

-- has(collectionname, attributename)

-- The ternary operator ?:

let attribute1 = has(doc,"attribute1") ?( 
        for name in doc.attribute1.names
        filter name.language == "xyz"
        return name.name
        ) : "" 

But this dosent work. Seems like arango compiler first attempts to compile the for loop, finds nulls and reports error as below. Instead, it should have compiled "has" function first for the ternary operator being used.

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

If there is a better way of doing it, would appreciate the advice!!

Thanks in advance! Nilotpal


Solution

  • Fakhrany here from ArangoDB.

    Regarding your question, this is a known limitation. From https://docs.arangodb.com/3.11/aql/fundamentals/limitations/ :

    The following other limitations are known for AQL queries:

    Subqueries that are used inside expressions are pulled out of these expressions and executed beforehand. That means that subqueries do not participate in lazy evaluation of operands, for example in the ternary operator. Also see evaluation of subqueries.

    Also noted here for the ternary operator: https://docs.arangodb.com/3.11/aql/operators/#ternary-operator

    An answer to the question what to do may be to use a FILTER before enumerating over the attributes:

    FOR doc IN collection 
      /* the following filter will only let those documents passed in which "attribute1.names" is an array */
      FILTER IS_ARRAY(doc.attribute1.names) 
      FOR name IN doc.attribute1.names
        FILTER name.language == "xyz"
        RETURN name.name
    

    Other solutions are also possible. Depends a bit on the use case.