Query ElasticSearch by array filter length - arrays

I have a prop containing an array of integers:
_source: {
counts: [
11,
7,
18,
3,
22
]
}
From another post I know that I can filter by a range using:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"range": {
"counts": {
"gte": 10,
"lte": 20
}
}
}
}
}
}
However, I need to additionally know if the range match count is greater than a certain number. For instance, I only want records back which have less than 3 counts matching between 10 and 20.

Mapping used:
{
"properties" : {
"counts" : {
"type" : "integer"
}
}
}
These are the docs I indexed:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "test",
"_id": "2",
"_score": 1,
"_source": {
"counts": [
13,
17
]
}
},
{
"_index": "test_index",
"_type": "test",
"_id": "1",
"_score": 1,
"_source": {
"counts": [
11,
7,
18,
3,
22
]
}
},
{
"_index": "test_index",
"_type": "test",
"_id": "3",
"_score": 1,
"_source": {
"counts": [
11,
19
]
}
}
]
}
}
Now try this query:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": [
{"script" : { "script" : "doc['counts'].values.size() < 4" }},
{"range": { "counts": { "gte": 10, "lte": 20 } }}
]
}
}
}
Results: Only doc id 2 and 3 are returned. Doc 1 is not returned.
{
"took": 29,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "test",
"_id": "2",
"_score": 1,
"_source": {
"counts": [
13,
17
]
}
},
{
"_index": "test_index",
"_type": "test",
"_id": "3",
"_score": 1,
"_source": {
"counts": [
11,
19
]
}
}
]
}
}
Is this what you are trying to do?

Related

Elasticsearch query: combine nested array of objects into one array

Using Elasticsearch I am trying to combine a nested array of objects into one array.
This is what my data looks like:
GET invoices/_search
{
"hits": [
{
"_index": "invoices",
"_id": "1234",
"_score": 1.0,
"_source": {
"id": 1234,
"status": "unpaid",
"total": 15.35,
"payments": [
{
"id": 1981,
"amount": 10,
"date": "2022-02-09T13:00:00+01:00"
},
{
"id": 1982,
"amount": 5.35,
"date": "2022-02-09T13:35:00+01:00"
}
]
}
},
# ... More hits
]
}
I want to only get the payments array of each hit combined into one array, so that it returns something like this:
{
"payments": [
{
"id": 1981,
"amount": 10,
"date": "2022-02-09T13:00:00+01:00"
},
{
"id": 1982,
"amount": 5.35,
"date": "2022-02-09T13:35:00+01:00"
},
{
"id": 5658,
"amount": 3,
"date": "2021-12-19T13:00:00+01:00"
}
]
}
I tried to get this result using nested queries but could not figure it out, the query I used is:
# Query I used:
GET invoices/_search
{
"_source": ["payments"],
"query": {
"nested": {
"path": "payments",
"query": {
"bool": {
"must": [
{
"exists": {
"field": "payments.id"
}
}
]
}
}
}
}
}
# Result:
{
"hits": [
{
"_index": "invoices",
"_id": "545960",
"_score": 1.0,
"_source": {
"payments": [
{
"date": "2022-01-22T15:38:15+01:00",
"amount": 374.5,
"id": 320320
},
{
"date": "2022-01-22T15:30:03+01:00",
"amount": 160.5,
"id": 320316
}
]
}
},
{
"_index": "invoices",
"_id": "545961",
"_score": 1.0,
"_source": {
"payments": [
{
"date": "2022-01-22T15:38:15+01:00",
"amount": 12,
"id": 320350
},
{
"date": "2022-01-22T15:30:03+01:00",
"amount": 60.65,
"id": 320379
}
]
}
}
]
}
The result returns only the payments array but divided over multiple hits. How can I combine those arrays?

How to sort words by their relevance to a keyword?

I'm currently working on a search using elasticsearch. We have a very large amount of users.
Here is the elasticsearch mapping:
PUT /example_index/_mapping/users
{
"properties": {
"user_autocomplete": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
},
"completion": {
"type": "text",
"analyzer": "user_autocomplete_analyzer",
"search_analyzer": "standard"
}
}
},
"firstName": {
"type": "text"
},
"lastName": {
"type": "text"
}
}
}
Here is the search query.
For example, I get 3 records
GET example_index/users/_search
{
"from": 0,
"size": 3,
"query": {
"query_string": {
"query": "*ro*",
"fields": [
"firstName",
"lastName"
]
}
},
"aggs": {
"user_suggestions": {
"terms": {
"size": 3,
"field": "user_autocomplete.raw"
}
}
}
}
Here is the output of elasticsearch
{
"took": 53,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 13,
"max_score": 1,
"hits": [
{
"_index": "example_index",
"_type": "users",
"_id": "08",
"_score": 1,
"_source": {
"firstName": "Eero",
"lastName": "Saarinen",
"user_autocomplete": "Eero Saarinen"
}
},
{
"_index": "example_index",
"_type": "users",
"_id": "16",
"_score": 1,
"_source": {
"firstName": "Aaron",
"lastName": "Judge",
"user_autocomplete": "Aaron Judge"
}
},
{
"_index": "example_index",
"_type": "users",
"_id": "20",
"_score": 1,
"_source": {
"firstName": "Robert",
"lastName": "Langdon",
"user_autocomplete": "Robert Langdon"
}
}
]
},
"aggregations": {
"user_suggestions": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 10,
"buckets": [
{
"key": "Eero Saarinen",
"doc_count": 1
},
{
"key": "Aaron Judge",
"doc_count": 1
},
{
"key": "Robert Langdon",
"doc_count": 1
}
]
}
}
}
I need result like in the following order:
Robert Langdon
Aaron Judge
Eero Saarinen
I have tried order method. It won't work. Is there a way to do this?

error when trying to filter an array to get a subset in angular

I am trying to filter objects array based on the value of one of the parameters in the array. However when i try to do the same, an error is thrown "Argument '[value] is not a function, got undefined.
$scope.model.selection will contain array values based on user selections(say checkboxes)
$scope.model.selection = ["m1", "m2"]
I have written the code to get only the _source values from the json as objects. Now i want only the objects which passes a particular condition viz machinename in ["m1"]
My code:
var filter;
filter = sourcearray.filter(function (filterinstance)
{
return filterinstance.machinename in $scope.model.selection;
});
My data:
{
"kal": [
{
"_index": "log2015.18",
"_type": "MT_DETAIL",
"_sc": null,
"_source": {
"value1": 0,
"value2": "2",
"value3": "MON",
"machine": "m1"
},
"sort": [
1
]
},
{
"_index": "logw-2015.18",
"_type": "MT_DETAIL",
"_sc": null,
"_source": {
"value1": 1,
"value2": "3",
"value3": "MON1",
"machine": "m1"
},
"sort": [
2
]
},
{
"_index": "log-2015.18",
"_type": "MT_DETAIL",
"_sc": null,
"_source": {
"value1": 3,
"value2": "265",
"value3": "MON2",
"machine": "m2"
},
"sort": [
3
]
},
{
"_index": "log2015.18",
"_type": "MT_DETAIL",
"_sc": null,
"_source": {
"value1": 4,
"value2": "5",
"value3": "MON5",
"machine": "m2"
},
"sort": [
1
]
},
{
"_index": "log2015.18",
"_type": "MT_DETAIL",
"_sc": null,
"_source": {
"value1": 7,
"value2": "3",
"value3": "MON8"
},
"sort": [
1
]
}
]
}

Array included in array search with elasticsearch

I have users indexed with categories as follows
{
id: 1
name: John
categories: [
{
id: 1
name: Category 1
},
{
id: 2
name: Category 2
}
]
},
{
id: 2
name: Mark
categories: [
{
id: 1
name: Category 1
}
]
}
And I'm trying to get all the documents with Category 1 or Category 2 with
{
filter:
{
bool: {
must: [
{
terms: {user.categories.id: [1, 2]}
}
]
}
}
}
But It only returns the first document that has the two categories, what I am doing wrong?
As I understood, terms search that one of the values is contained in the field, so for user 1
user.categories.id: [1, 2]
user 2
user.categories.id: [1]
Categoy id 1 is contained in both documents
The best way to handle this is probably with a nested filter. You'll have to specify the "nested" type in your mapping, though.
I can set up an index like this:
PUT /test_index
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"doc": {
"properties": {
"categories": {
"type": "nested",
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "string"
}
}
},
"id": {
"type": "long"
},
"name": {
"type": "string"
}
}
}
}
}
then add some docs:
PUT /test_index/doc/1
{
"id": 1,
"name": "John",
"categories": [
{ "id": 1, "name": "Category 1" },
{ "id": 2, "name": "Category 2" }
]
}
PUT /test_index/doc/2
{
"id": 2,
"name": "Mark",
"categories": [
{ "id": 1, "name": "Category 1" }
]
}
PUT /test_index/doc/3
{
"id": 3,
"name": "Bill",
"categories": [
{ "id": 3, "name": "Category 3" },
{ "id": 4, "name": "Category 4" }
]
}
Now I can use a nested terms filter like this:
POST /test_index/doc/_search
{
"query": {
"constant_score": {
"filter": {
"nested": {
"path": "categories",
"filter": {
"terms": {
"categories.id": [1, 2]
}
}
}
},
"boost": 1.2
}
}
}
...
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"name": "John",
"categories": [
{
"id": 1,
"name": "Category 1"
},
{
"id": 2,
"name": "Category 2"
}
]
}
},
{
"_index": "test_index",
"_type": "doc",
"_id": "2",
"_score": 1,
"_source": {
"id": 2,
"name": "Mark",
"categories": [
{
"id": 1,
"name": "Category 1"
}
]
}
}
]
}
}
Here is the code I used:
http://sense.qbox.io/gist/668aefe910643b52a3a10d40aca67104491668fc

ElasticSearch Read element on array

I'm working with Elasticsearch, currently I have a struct like that
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "999999",
"_type": "content",
"_id": "NmYTku",
"_score": 1,
"_source": {
"internal_id": "NmYTk4",
"external_id": "Ga_UI502",
"
"images": [
{
"uri_id": "2939306",
"url": "14mast_head.jpg",
"type": "Masthead",
"orientation": "Landscape",
"x_resolution": 3280,
"y_resolution": 1480
},
{
"uri_id": "Galavision/POST_poster/2939306",
"url": "140603_29un_erro_poster.jpg",
"type": "Poster",
"orientation": "Portrait",
"x_resolution": 720,
"y_resolution": 405
},
{
"uri_id": "Galavision/POST_poster_title/2939306",
"url": "140603_29un_erro_poster_title.jpg",
"type": "PosterWithTitle",
"orientation": "Portrait",
"x_resolution": 924,
"y_resolution": 518
},
{
"uri_id": "Galavision/POST_poster_cover/2939306",
"url": "140603_29poster_cover.jpg",
"type": "Poster",
"orientation": "Landscape",
"x_resolution": 600,
"y_resolution": 868
}
]
}
}
]
}
}
I was wondering, how can I get only one value from my array e.g.
I want to have only the images with oritentation on Landscape and type Poster. I tried with This query but it only returns me all the image elements.
{
"query": {
"filtered": {
"filter": { "term":{"_id":"NmYTku"} }
}
},
"_source": ["images"]
}
I don't have idea how do a filter on the elements
Are you using nested or child fields for the images? If not, that doc is actually being indexed like:
...
images.uri_id = [1, 2, 3, 4, etc..]
images.url = [1, 2, 3, 4, etc..]
images.type = [1, 2, 3, 4, etc..]
...
so the distinction between individual elements is gone. Try giving this a read:
http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/complex-core-fields.html
If you don't need to query, why not just filter out the ones you like client side?
Try this:
{
"filtered": {
"query": {
"match": { "term": "_id" : "NmYTku" }
},
"_source": [images]{
"orientation": "landscape",
"type": "Poster",
}
}

Resources