How to get elasticsearch suggestions working on multiple fields from multiple types? - elasticsearch

I have a requirement to have a search box globally on the website that user can type anything in, a bit like google. As the user is typing along, he should get suggestions. I have multiple types in an Index, I am using Completion suggester to get suggestions from one field like below:
GET /index/_suggest/
{
"person-suggest" : {
"text" : "m",
"completion" : {
"field" : "nameSuggest"
}
}
}
The requirement is such that when they type a person name which is stored in person type or type in a company name which is stored in company type...both suggestions should appear. Also, within the same type, it should be able to suggest based on multiple fields not just one like what I've got. And finally once the user selects a suggestion, do a search and show facets which are based on multiple types.

For multi-type suggestions on multiple fields, use-
curl -XPOST 'localhost:9200/indexName/type1,type2/_suggest' -d '{
"my-suggestion-1" : {
"text" : "some text",
"term" : {
"field" : "field1"
}
},
"my-suggestion-2" : {
"text" : "some text",
"term" : {
"field" : "field2"
}
}
}'

Related

elasticsearch doesn't suggesting anything if the exact word is used as text?

I'm using text suggester of elasticsearch. My index contains a document which has a filed name and its value is crick
{
"suggest": {
"my-suggest" : {
"text" : "crick",
"term" : {
"field" : "name",
"sort": "score"
}
}
}
}
it return no match, it only returns a value if there is a misspelled
if I pass the exact text it return nothing any idea !!
You are not using suggest_mode
The suggest mode controls what suggestions are included or controls for what suggest text terms, suggestions should be suggested. Three possible values can be specified:
missing: Only provide suggestions for suggest text terms that are not in the index. This is the default.
popular: Only suggest suggestions that occur in more docs then the original suggest text term.
always: Suggest any matching suggestions based on terms in the suggest text.
Since you haven't mentioned suggest_mode it is picking missing by default.
use this settings
{
"suggest": {
"my-suggest" : {
"text" : "crick",
"term" : {
"field" : "name",
"sort": "score",
"suggest_mode": "always"
}
}
}
}

Aggregation on different document type

i'm trying to solve a problem here, I'm not even sure it can be done how I want it to be done.
Basically I need to query my index on the type Company. This type does have a field named Company_Name. Now I have another type which is Employee that does have a field named Company_Name as well, which basically "links him" to the Company.
What I need to do is to make an aggregation in my query of companies, that gets me the number of employees that are within the company (for each result).
Any way to do this ?
EDIT :
The mapping :
"company" : {
"properties" : {
"company_name" : {
"type" : "text"
}
}
},
"employee" : {
"properties" : {
"employee_name" : {
"type" : "text"
},
"company_name" : {
"type" : "text"
}
}
}
Not sure if I fully understood what you want but you mentioned:
Now I have another type which is Employee that does have a field named Company_Name
And then you said you want, number of employees that are withing the company.
So for me it looks like all you need is an aggregation on Employees doc type by company.
If you really need to query both indexes then you can apply a multi-index search and the aggregation to the result of the multi index search.
This or something close to this should work:
http://localhost:9200/$index/employee/_search?search_type=count
{
"aggs" : {
"company" : {
"terms" : {
"field" : "company_name"
}
}
}
}
One think you should notice is that if your field company_name is analyzed it will be tokenized and you can't aggregate on that. You should then add a raw field with company name to use for your aggregation.
Some useful references:
https://www.elastic.co/guide/en/elasticsearch/guide/current/relations.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/_closing_thoughts.html and

Elasticsearch document aliases

I have multiple mappings which come from the same datasource but have small differences, like the example below.
{
"type_A" : {
"properties" : {
"name" : {
"type" : "string"
}
"meta_A" : {
"type" : "string"
}
}
}
}
{
"type_B" : {
"properties" : {
"name" : {
"type" : "string"
}
"meta_B" : {
"type" : "string"
}
}
}
}
What I want to be able to is:
Directly query specific fields (like meta_A)
Directly query all documents from the datsource
Query all documents from a specific mapping
What I was looking into is the type filter, so preferably I could write a query like this:
{
"query": {
"filtered" : {
"filter" : {
"type" : { "value" : "unified_type" }
}
}
// other query clauses
}
}
So instead of typing "type_A","type_B" in an or clause in the type filter I would like to have this "unified_type", but without giving up the possibility to directly query "type_A".
How could I achive this?
I don't think that it's possible. However, you could use copy_to functionality, so you would have your fields as they are now and their values copied into unified name.
The copy_to parameter allows you to create custom _all fields. In
other words, the values of multiple fields can be copied into a group
field, which can then be queried as a single field. For instance, the
first_name and last_name fields can be copied to the full_name field
as follows:
So you'd be copying both "meta_A" and "meta_B" into some "unified_meta" field and query this one.

What's the reason for specifying only the 'field' option for the Term & Phrase suggesters in elasticsearch

When using the suggester API, we are forced to specify the field option :
"suggest" : {
"text" : "val",
"sug_name" : {
"term" : {
"field" : "field_name"
}
}
}
Is this field supposed to be a valid field name of some type ?
If so, fields can exist only in the context of types AFAIK.
Why isn't possible to also specify (at least optionally) the type the field belongs to ?
Is your question if "field" has to be a valid field?
YES it does if you want it to find anything, you are welcome to search for fields that dont exist, although that seems an odd thing to do.
Your second question, the answer, I believe, is NO, you can not specify a _type using the _suggest api, you can use a suggest block with the _search api as shown here
curl -s -XPOST 'localhost:9200/_search' -d '{
"query" : {
...
},
"suggest" : {
...
}
}'

Full-text schema in ElasticSearch

I'm (extremely) new to ElasticSearch so forgive my potentially ridiculous question. I currently use MySQL to perform full-text searches, and want to move this to ElasticSearch. Currently my table has a fulltext index spanning three columns:
title,description,tags
In ES, each document would therefore have title, description and tags fields, allowing me to do a fulltext search for a general phrase, or filter on a given tag.
I also want to add further searchable fields such as username (so I can retrieve posts by a given user). So, how do I specify that a fulltext search should match title OR description OR tags but not username?
From the OR filter example, I'd assume I'd have to use something like this:
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"or" : [
{
"term" : { "title" : "foobar" }
},
{
"term" : { "description" : "foobar" }
},
{
"term" : { "tags" : "foobar" }
}
]
}
}
}
Coming at this new, it doesn't seem like this is very efficient. Is there a better way of doing this, or do I need to move the username field to a separate index?
This is fine.
I general I would suggest getting familiar with ElasticSearch mapping types and options.
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping.html

Resources