Reputation: 381
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
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