elasticsearch nested query, i think - elasticsearch

I come from a related database background and something like this would be so simple there, but I can't figure this out. I've been trying to learn Elasticsearch for a week or so and I'm trying to figure out what I think is a nested query. Here's some sample data:
PUT /myindex/pets/_mapping
{
"pets": {
"properties": {
"name": {
"type": "string"
},
"pet": {
"type": "nested",
"properties": {
"name": {"type": "string"}
}
}
}
}
}
POST /myindex/pets/
{"pet": {"name": "rosco"}, "name": "sam smith"}
POST /myindex/pets/
{"pet": {"name": "patches"}, "name": "sam smith"}
POST /myindex/pets
{"pet": {"name": "rosco"}, "name": "jack mitchell"}
What would the query look like that only returns documents matching:
owner name is "sam smith"
pet name is "rosco"
I've tried a mixmatch of bool, match, nested, filtered/filter type queries, but I just keep getting errors. Stuff like this stands out in the errors:
nested: ElasticsearchParseException[Expected field name but got START_OBJECT \"nested\"];
Here was the query:
GET /myindex/pets/_search
{
"query": {
"match": {
"name": "sam smith"
},
"nested": {
"path": "pet",
"query": {
"match": {
"pet.name": "rosco"
}
}
}
}
}
I'm beginning to think that I just can't target something this specific due to the relevant nature of Elasticsearch.
Any ideas?

Man, these queries are tricky sometimes... This seems to work:
GET /myindex/pets/_search
{
"query": {
"filtered": {
"query": {
"match": {
"name": "sam smith"
}
},
"filter": {
"nested": {
"path": "pet",
"query": {
"match": {
"pet.name": "rosco"
}
}
}
}
}
}
}

Related

How to boost specific terms in elastic search?

If I have the following mapping:
PUT /book
{
"settings": {},
"mappings": {
"properties": {
"title": {
"type": "text"
},
"author": {
"type": "text"
}
}
}
}
How can i boost specific authors higher than others?
In case of the below example:
PUT /book/_doc/1
{
"title": "car parts",
"author": "john smith"
}
PUT /book/_doc/2
{
"title": "car",
"author": "bob bobby"
}
PUT /book/_doc/3
{
"title": "soap",
"author": "sam sammy"
}
PUT /book/_doc/4
{
"title": "car designs",
"author": "joe walker"
}
GET /book/_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "car" }},
{ "match": { "title": "parts" }}
]
}
}
}
How do I make it so my search will give me books by "joe walker" are at the top of the search results?
One solution is to make use of function_score.
The function_score allows you to modify the score of documents that are retrieved by a query.
From here
Base on your mappings try to run this query for example:
GET book/_search
{
"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"match": {
"title": "car"
}
},
{
"match": {
"title": "parts"
}
}
]
}
},
"functions": [
{
"filter": {
"match": {
"author": "joe walker"
}
},
"weight": 30
}
],
"max_boost": 30,
"score_mode": "max",
"boost_mode": "multiply"
}
}
}
The query inside function_score is the same should query that you used.
Now we want to take all the results from the query and give more weight (increase the score) to joe walker's books, meaning prioritize its books over the others.
To achieved that we created a function (inside functions) that compute a new score for each document returned by the query filtered by joe walker books.
You can play with the weight and other params.
Hope it helps

Elastic Search URI Search Filtering

I have a movies ES index with the following mapping:
{
"doc": {
"properties": {
"director": {
"type": "text"
},
"genres": {
"type": "text",
"index": "false"
},
"title": {
"type": "text"
},
"year": {
"type": "long"
}
}
}
}
For genres, I'll be submitting an array of strings. Now, I want to allow my customers to submit a query against my endpoint, where I'd proxy q request parameter down to ES client.
But I am struggling to filter the data with the URI search the same way it can be achieved by submitting a query as a payload against my index. For instance:
GET movies/doc/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"term": {
"genres": "War"
}
}
],
"must": [
{
"term": {
"genres": "Foo"
}
}
],
"must": [
{
"term": {
"genres": "Bar"
}
}
]
}
}
}
}
}
Can the same be achieved via URI search? If so, how?
From ES documentation
You can use query parameters to define your search criteria directly
in the request URI, rather than in the request body. Request URI
searches do not support the full Elasticsearch Query DSL, but are
handy for testing.
Based on our discussion, I suggest you build a DSL query in the backend after receiving request from the client. You need to expose an API which will send UI inputs to the backend in a structured format(JSON) which can help you build the DSL query easily.
Here is how I ended up doing it, without the q parameter. Version 6.0.1:
POST http://127.0.0.1:9200/movies/_mapping/doc
{
"doc": {
"properties": {
"director": {
"type": "text"
},
"title": {
"type": "text"
},
"year": {
"type": "long"
},
"genres": {
"type": "keyword"
}
}
}
}
Create documents:
POST http://127.0.0.1:9200/movies/doc/
{
"title": "title 1",
"director": "Igor M",
"year": 2011,
"genres": ["Bar", "Foo"]
}
Query for documents:
GET http://127.0.0.1:9200/movies/_search
{
"query": {
"bool": {
"must":[
{ "match": { "genres": "War" }},
{ "match": { "genres": "Bar" }}
]
}
}
}

How to search on multiple fields in URI Search

I would like to perform an AND operation in ElasticSearch using the URI Search (q=). How do I do it?
If I have document like:
[{ "name":"Test 1", "pub":"2"}, { "name":"Test 2", "pub":"1"}, { "name":"A", "pub":"1"}]
And I would like to query for documents containing with a name containing "Test" AND where pub equals "1". How do I do that?
Thanks!
Assuming your document looks like this:
{
"my_field": [
{ "name":"Test 1", "pub":"2"},
{ "name":"Test 2", "pub":"1"},
{ "name":"A", "pub":"1"}
]
}
And the mapping of my_field is of type nested similar to this:
{
"mappings": {
"doc_type": {
"properties": {
"my_field": {
"type": "nested",
"properties": {
"name": { "type": "string" },
"pub": {"type": "integer" }
}
}
}
}
}
}
Then you can query your index and get the expected documents with the following nested query:
POST /_search
{
"query": {
"nested": {
"path": "my_field",
"query": {
"bool": {
"filter": [
{
"match": {
"name": "Test"
}
},
{
"match": {
"pub": 1
}
}
]
}
}
}
}
}
Actually you'd need nested fields. The following is a good resource.
https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-objects.html

elasticsearch search results with sub query

Getting started with elasticsearch, not sure if this is possible with one query along with pagination. I have a index with two types: user & blog. Example mapping:
"mappings": {
"user": {
"properties": {
"name" : { "type": "string" }
}
},
"blog": {
"properties": {
"title" : { "type": "string" },
"author_name" : { "type": "string" }
}
}
}
}
sample data
user:
[
{"name": "jemmy"},
{"name": "Tom"}
]
blog:
[
{"title": "foo bar", "author": "jemmy"},
{"title": "magic foo", "author": "Tom"},
{"title": "bigdata for dummies", "author": "Tom"},
{"title": "elasticsearch", "author": "Tom"},
{"title": "JS cookbook", "author": "jemmy"},
]
I'd like to query on the index such a way that when I search for blog it should do subquery on on each match. For example:
POST /test_index/blog/_search
{
"query": {
"match": {
"_all": "foo"
}
}
}
Expected (pseudo) results:
[
{
title: "foo bar",
author_name: "Jemmy",
author_post_count: 2
},
{
title: "magic foo",
author_name: "Tom",
author_post_count: 3
}
]
Here author_post_count is blog post count that the user has authored. If it could return those blog posts instead of count that would be great too. Is this possible? Perhaps the term i'm using not right, but I hope my question is clear.
Try something like this:
POST /test_index/blog/_search
{
"query": {
"match": {
"_all": "foo"
}
},
"aggs": {
"counting_posts": {
"global": {},
"aggs": {
"authors": {
"terms": {
"field": "author",
"size": 10
}
}
}
}
}
}
Be careful though with terms aggregation because it is considering the actual tokenized list of terms from the index, not what you actually index (lowercase/uppercase, tokenized in a way or another).

ElasticSearch - multi-match with filter - returns no result

I have a problem. My search result returns zero when I add a filter in my JSON request
{
"body":
{
"query":{
"multi_match":
{
"query":"Joe Jerick Aparments",
"fields":["name","Category","address","description"]}
},
"filter":
{
"source":"Category":"Apartments"
}
}
}
First things first,
Yes, there is already data.
Yes there is no error
Yes there is no misspelled words
Thanks!
{
index: "stores",
type: "stores",
id: "1",
body: {
name: "Joe Jerick Apartments",
Category: "Apartments"
address: "Somewhere down the road",
description: "Best apartment yet!"
}
}
So, I didn't see this in my earlier comment but if the fields you're querying on are nested inside of body (in storage -- not in retrieval) you'll need a nested query to get at the fields listed (I'm not sure if you're describing your mapping or what it looks like on query retrieval for a match_all)
If this is the case you'll need body to be mapped as "nested" and then your query would look something like this.
{
"query": {
"filtered": {
"query": {
"multi_match": {
"query": "Joe Jerick Apartments",
"fields": [
"body.name",
"body.Category",
"body.address",
"body.description"
]
}
},
"filter": {
"term": {
"body.Category": "Apartments"
}
}
}
}
}
Altertively you could re-import your records with a flattened structure
{
"id": "1",
"name": "Joe Jerick Apartments",
"Category": "Apartments",
"address": "Somewhere down the road",
"description": "Best apartment yet!"
}
Try this query instead:
{
"query": {
"filtered": {
"query": {
"multi_match": {
"query": "Joe Jerick Apartments",
"fields": [
"name",
"Category",
"address",
"description"
]
}
},
"filter": {
"term": {
"Category": "Apartments"
}
}
}
}
}

Resources