Struggling with making this ES query. Basically, I have a nested object, something like:
{
"id": "00000000-0000-0000-0000-000000000000",
"exchangeRate": 0.01,
"payments": [
{
"id": "00000000-0000-0000-0000-000000000000",
"paymentId": "some-id",
"currency": "USD",
"amount": 400.0
},
{
"id": "00000000-0000-0000-0000-000000000000",
"currency": "USD",
"paymentId": "some-id2",
"amount": -200.0
},
{
"id": "00000000-0000-0000-0000-000000000000",
"currency": "USD",
"amount": -200.0
}
]
}
And I want to match on an object where some of the "paymentId" keys are defined, but not all. So the above object would be a match. Whereas something like:
{
"id": "00000000-0000-0000-0000-000000000000",
"exchangeRate": 0.01,
"payments": [
{
"id": "00000000-0000-0000-0000-000000000000",
"paymentId": "some-id",
"currency": "USD",
"amount": 400.0
},
{
"id": "00000000-0000-0000-0000-000000000000",
"currency": "USD",
"paymentId": "some-id2",
"amount": -200.0
},
{
"id": "00000000-0000-0000-0000-000000000000",
"currency": "USD",
"paymentId": "some-id3",
"amount": -200.0
}
Would not match.
I've made a query which matches if all paymendIds are defined and returns all objects where that is true. This query is:
{
"query": {
"bool": {
"must": {
"nested": {
"path": "payments",
"query": {
"exists": {
"field": "payments.paymendIds"
}
}
}
}
}
}
}
The question would be how do I reverse this? So that if it matches this query, it doesn't return as a match. As putting "must_not" simply does the opposite. It returns all records that don't have any paymentIds defined at all. Which is something I want to match on, but I need all the ones that even have only some of the paymentIds set.
You could compare the payments
objects' field value sizes one by one while in the nested
context.
Assuming both payments.id
and payments.paymentId
are of the keyword
mapping type, you could say:
GET your-index/_search
{
"query": {
"nested": {
"path": "payments",
"query": {
"script": {
"script": "doc['payments.id'].size() != doc['payments.paymentId'].size()"
}
}
}
}
}