Blob
Blob

Reputation: 381

Unable to filter for multiple features with JMESPath

My data looks as follows. How come I am able to filter for one word using contains but not a list of words I wish to filter for? both queries should produce the same output

import jmespath

data = {'collection': {'items': {'word': 'ice-cube'}}}
jmespath.search(
  'values(collection)[?word!=null && contains([`cube`,`-`],word)]', 
  data
) # returns []
jmespath.search(
  'values(collection)[?word!=null && contains(word,`cube`)]', 
  data
) # works

Upvotes: 1

Views: 238

Answers (1)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39294

The signature of the function contains is

boolean contains(array|string $subject, any $search)

So, when you are doing

contains([`cube`, `-`], word)

You are actually looking for the value of the property word in the array [`cube`, `-`], and not the other way around, as you are doing it in

contains(word, `cube`)

Where you are indeed searching for cube in the value of the property word.

Furthermore:

If $subject is an array, this function returns true if one of the elements in the array is equal to the provided $search value.

Source: https://jmespath.org/specification.html#contains

Which means you have to have exact match of what you are searching for in the subject, which is not what you are trying to do here.


For your requirement, you will have to construct the query with multiple contains:

collection.* | [?word && contains(word, `-`) && contains(word, `cube`)]

Which you can easily do, since you are doing your query with the Python library.

For example:

import jmespath

data = {'collection': {'items': {'word': 'ice-cube'}}}
terms = {'cube', '-'}
contains = [f'contains(word, `{term}`)' for term in terms]
print(
  jmespath.search(
    f'collection.* | [?word && {" && ".join(contains)}]',
    data
  )
)

Would yield:

[{'word': 'ice-cube'}]

Upvotes: 1

Related Questions