Search code examples
arangodbaqlpython-arango

Using "COUNT INTO length" or Aggregate-functions in a regular filtered Query


I'm using Python to access my ArangoDB. Sometimes it would be useful to figure out if the result is empty or if I have exactly one result by using len(cursor).

This unfortunately leads mostly to an exception:

│arango.exceptions.CursorCountError: cursor count not enabled

In the source code of the cursor it seems there needs to be a count-variable in the resultset.

According to the documentation this is done by adding:

COLLECT WITH COUNT INTO length

In my case I'm using a simple, mostly automatically generated query filtering everything:

FOR i IN nodes 
FILTER i.ID == "3000" OR i.ID == "3005" OR i.ID == "11235"
RETURN {'_id':i._id,'id':i.id}

Adding a COLLECT is resulting in an error. This post https://stackoverflow.com/a/24131344/2516892 would suggest a solution like that:

FOR m IN nodes
FILTER m.ID == "3000" OR m.ID == "3005" OR m.ID == "11235"
COLLECT WITH COUNT INTO length
RETURN {'_id':i._id,'id':i.id, 'length': length}

Which is not working. What would be the correct query inserting this kind of aggregate function?


Solution

  • The COLLECT WITH COUNT and the Cursor count are two distinct things. COLLECT WITH COUNT INTO length allows you to get one document as a result, with properties and the information how many documents have those distinct properties, e.g. how many of your users are between 25 and 30 years old.

    The cursor count is the information how many results are to be fetched all in all. According to the docs you have to specify that you want the cursor to provide this information during creation with count=True, like so:

    # Execute an AQL query which returns a cursor object.
    cursor = db.aql.execute(
        'FOR doc IN students FILTER doc.age > @val RETURN doc',
        bind_vars={'val': 17},
        batch_size=2,
        count=True
    )
    

    The reasoning behind this is, that it is costly to calculate that information (the result set length) up front, you want to avoid it if you can.

    Depending on your use-case it might be the better choice to not treat a cursor different when the result is empty or just containing one element.