I'm new in elastica search.
Can you help me with creating query ? I need search by name.
GET /site/file/_search
"hits": [
{
"_index": "site",
"_type": "file",
"_id": "135",
"_score": 1,
"_source": {
"userId": 0,
"name": "P1030021j.jpg",
"extension": "jpg",
"size": 1256
}
}
]
Thanks,
I find solution for my problem:
{
"fuzzy_like_this" : {
"fields" : ["name"],
"like_text" : "Search string",
"max_query_terms" : 12
}
}
Search by URL:
GET /site/file/_search?q=name:P1030021j.jpg
Search By Restful API
GET /site/file/_search
{
"query" : {
"query_string" : {
"query" : "name:P1030021j.jpg"
}
}
}
Related
I am trying to build a query, where I am using exact phrase match and synonyms and I can't figure it out. Also, when using wildcard approach I don't know how to use fuzziness. Is it even possible with wildcards? It would be great to get same results for terms "call of duty", "cod" or "call of dutz".
I have created this index:
PUT exact_search
{
"settings": {
"index": {
"number_of_shards": "1",
"number_of_replicas": "0",
"analysis": {
"analyzer": {
"analyzer_exact": {
"type": "custom",
"tokenizer": "keyword",
"filter": [
"lowercase",
"icu_folding",
"synonyms"
]
}
},
"filter": {
"synonyms": {
"type": "synonym",
"synonyms_path": "synonyms.txt"
}
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "keyword",
"fields": {
"analyzer_exact": {
"type": "text",
"analyzer": "analyzer_exact"
}
}
}
}
}
}
And I fill it with these items:
POST exact_search/_doc/1
{
"name": "Hoodie Call of Duty"
}
POST exact_search/_doc/2
{
"name": "Call of Duty 2"
}
POST exact_search/_doc/3
{
"name": "Call of Duty: Modern Warfare 2"
}
POST exact_search/_doc/4
{
"name": "COD: Modern Warfare 2"
}
POST exact_search/_doc/5
{
"name": "Call of duty"
}
POST exact_search/_doc/6
{
"name": "Call of the sea"
}
POST exact_search/_doc/7
{
"name": "Heavy Duty"
}
synonyms.txt looks like this:
cod,call of duty
And what I am trying to achieve is, to get all the results (exept call of the sea and heavy duty) when I search "call of duty" or "cod".
So far, I constructed this query, but it does not work as expected when using "cod" search term (term "call of duty" works fine):
GET exact_search/_search
{
"explain": false,
"query":{
"bool":{
"must":[
{
"wildcard": {
"name.analyzer_exact": {
"value": "*cod*"
}
}
}
]
}
}
}
But the result is only two items:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "exact_search",
"_id" : "4",
"_score" : 1.0,
"_source" : {
"name" : "COD: Modern Warfare 2"
}
},
{
"_index" : "exact_search",
"_id" : "5",
"_score" : 1.0,
"_source" : {
"name" : "Call of duty"
}
}
]
}
}
It looks like that the synonyms are working, because it returns "call of duty" game, but it ignores the wildcards - it won't return Call of Duty 2 for example.
I need to look for the exact phrase match, because I dont't want to get results Heavy Duty or Call of the sea (when words "call" and "duty" match).
Thank you for pointing me in the right direction.
I have my doubts if the analyzer would generate the tokens synonymous with the analyzer_exact "tokenizer": "keyword".
I would change a few things to make it work.
keyword -> standard
"analyzer_exact": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"synonyms"
]
}
I would use match phrase to eliminate names other than call of duty and cod.
{
"match_phrase": {
"name.analyzer_exact": "cod"
}
}
Response after changes
{
"hits": {
"hits": [
{
"_source": {
"name": "Call of duty"
}
},
{
"_source": {
"name": "COD: Modern Warfare 2"
}
},
{
"_source": {
"name": "Call of Duty 2"
}
},
{
"_source": {
"name": "hoddies Call of Duty"
}
},
{
"_source": {
"name": "Call of Duty: Modern Warfare 2"
}
}
]
}
Hello i want to do something like that with elasticsearch enter image description here
I already have some knowledge in elasticsearch but I can't understand how can I do this , multiple search
You can use a combination of bool/must/should clause to combine multiple conditions
{
"query": {
"bool": {
"should": [
{
"multi_match": {
"query": "tag"
}
},
{
"match": {
"answers": 0
}
},
{
"match": {
"user": 1234
}
},
{
"multi_match": {
"query": "words here",
"type": "phrase"
}
},
{
"match": {
"score": 3
}
},
{
"match": {
"isaccepted": "yes"
}
}
]
}
}
}
If you want to search on multiple fields then you can use multi_match query
If no fields are provided, the multi_match query defaults to the
index.query.default_field index settings, which in turn defaults to *.
This extracts all fields in the mapping that are eligible to term queries and filters the metadata fields. All extracted fields are then
combined to build a query.
Adding a working example with index data, search query, and search result
Index Data:
{
"answers": 0,
"isaccepted": "no"
}
{
"answers": 0,
"isaccepted": "yes"
}
Search Query:
{
"query": {
"multi_match" : {
"query" : "yes"
}
}
}
Search Result:
"hits": [
{
"_index": "67542669",
"_type": "_doc",
"_id": "1",
"_score": 0.2876821,
"_source": {
"answers": 0,
"isaccepted": "yes"
}
}
]
So I've set up an index with the following mapping:
PUT test_index
{
"mappings": {
"doc": {
"properties": {
"title": {
"type": "text"
},
"author": {
"type": "text"
},
"reader_stats": {
"type": "join",
"relations": {
"book": "reader"
}
}
}
}
}
}
each parent document represents a book and its children represent a reader of that book. However, if I was to run:
GET test_index/_search
{
"query":{"match_all":{}}
}
The results would be populated with both books and readers like so:
"hits" : [
{
"_index" : "test_index",
"_type" : "doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"title" : "my second book",
"author" : "mr author",
"reader_stats" : {
"name" : "book"
}
}
},
{
"_index" : "test_index",
"_type" : "doc",
"_id" : "7",
"_score" : 1.0,
"_routing" : "2",
"_source" : {
"name" : "michael bookworm",
"clicks" : 1,
"reader_stats" : {
"name" : "reader",
"parent" : 2
}
}
}
]
Is there some way I can exclude reader documents and only show books? I already used match_all in my app to grab books so it would be good if I can avoid having to change that query but I guess that's not possible.
Also I'm a bit confused as to how mappings work with join fields as there is no definition for what fields are required of child documents. For example, in my mapping there's nowhere to specify that 'reader' documents must have 'name' and 'clicks' fields. Is this correct?
You need to use has_child (to search only parent docs) and has_parent (to search only child docs) keywords in your query.
Is there some way I can exclude reader documents and only show books?
YES
Your query will be:
GET test_index/_search
{
"query": {
"has_child": {
"type": "reader",
"query": {
"match_all": {}
}
}
}
}
For more detail info you can take a look at here:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-has-child-query.html
I have indexed a number of documents in my Elasticsearch database and when I query for all them I see they have a structure like this:
GET http://localhost:9200/restaurants/restaurant/_search
Output:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 362,
"max_score": 1,
"hits": [
{
"_index": "restaurants",
"_type": "restaurant",
"_id": "2",
"_score": 1,
"_source": {
"businessName": "VeeTooNdoor Dine",
"geoDescription": "Right next to you2",
"tags": {},
"location": {
"lat": -33.8917007446,
"lon": 151.1369934082
}
}
},
...
]
}
}
I now want to search for restaurants around a given geo-location and following the documentation [1] I use something like this:
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_distance" : {
"distance" : "1km",
"location" : {
"lat": -33.8917007446,
"lon": 151.1369934082
}
}
}
}
}
The thing I have changed is the match_all since I don't want to specify any search field in particular, I only care about the geo location.
When I run the query I get the following message:
"error": "SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; shardFailures {[olAoWBSJSF2XfTnzEhKIYA][btq][3]: SearchParseException[[btq][3]: from[-1],size[-1]: Parse Failure [Failed to parse source [{\n \"filtered\" : {\n \"query\" : {\n \"match_all\" : {}\n },\n \"filter\" : {\n .....
Now I did notice the following on the tutorial page:
Update: The automatic mapping of “geo enabled” properties has been
disabled since publishing this article. You have to provide the
correct mapping for geo properties. Please see the documentation.
Which gives me the impression that I have to create a "mapping" which specifies the field types. However, in the document it refers to doesn't give me enough information on how to actually do this. It shows blobs of JSON but I'm not sure about the correct URL's for this.
Further more, I'm using the PHP client and I'm not sure if it even supports mappings as is demonstrated in this walk through [2].
I somehow get the impression that quite a bit of changes have been made to the query DSL etc. and that a lot of examples on the web don't work anymore, I could be wrong through. I'm using Elasticsearch 1.0.0.
[1] http://www.elasticsearch.org/blog/geo-location-and-search
[2] http://blog.qbox.io/elasticsearch-aggregations
Things that might be wrong:
1: your query shows pin.location and your field is just location.
2: your _mapping for location could be wrong
Does your mapping show something like:
"location": {
"type": "geo_point",
"geohash_precision": 4
}
I was able to run this search against some of my own data:
POST /myindex/mydata/_search
{
"query": {
"match_all": {}
},
"filter": {
"geo_distance" : {
"distance" : "100km",
"_latlng_geo" : {
"lat": -33.8917007446,
"lon": 151.1369934082
}
}
}
}
... a snippet of my mapping:
"properties": { .....
"_latlng_geo": {
"type": "geo_point",
"geohash_precision": 4
}
.....
EDIT : How to use Put Mapping API
You can create the mapping when you create the index like so:
PUT /twitter/
{
"settings" : {
"number_of_shards" : 1
},
"mappings" : {
"tweet":{
"properties":{
"latlng" : {
"type" : "geo_point"
}
}
}
}
}
removing the query is what finally worked for me:
{
"filter": {
"geo_distance" : {
"distance" : "300km",
"location" : {
"lat" : 45,
"lon" : -122
}
}
}
}
You have to replace "location" by "restaurant.location" because ElasticSearch interprete it like a type not like a attribute.
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_distance" : {
"distance" : "1km",
"restaurant.location" : {
"lat": -33.8917007446,
"lon": 151.1369934082
}
}
}
}
I hope it helps you.
As stated in the docs:
"We use the generic PHP stdClass object to represent an empty object. The JSON will now encode correctly."
http://www.elasticsearch.org/guide/en/elasticsearch/client/php-api/current/_dealing_with_json_arrays_and_objects_in_php.html
In your case you should use
$searchParams['body']['query']['filtered']['query']['match_all'] = new \stdClass();
Using PHP and Mongo I would like to update the users availability but cannot figure it out. How can I structure my collection to be able to reference availability groups.steve.availability?
Below is the structure of my "groups" collection:
{
"_id": {
"$oid": "524327d536b82c7c5c842f6d"
},
"group_id": "testing",
"password": "test",
"users": [
{
"username": "steve",
"availability": "null"
},
{
"username": "joeb",
"availability": "null"
}
]
}
If you want to reference it the way you've suggested: groups.steve.availability, you'd need to structure your documents more like below. (I'm not sure where groups is coming from).
This example would give you users.steve.availability by moving the user's name to a sub-field of the users field (users.steve).
{
"_id": {
"$oid": "524327d536b82c7c5c842f6d"
},
"group_id": "testing",
"password": "test",
"users": {
"steve": {
"availability": "null"
},
"joeb" : {
"availability": "null"
}
}
}
Or, you could just create fields directly on the document:
{
"_id": {
"$oid": "524327d536b82c7c5c842f6d"
},
"group_id": "testing",
"password": "test",
"steve": {
"availability": "null"
},
"joeb" : {
"availability": "null"
}
}
That would allow you to just use steve.availability.
If you're trying to do a query though, you'd be better off leaving it more like you had it originally:
"users": [
{
"username": "steve",
"availability": "null"
}]
So, you could write queries that were like:
db.groups.find({"users.username" : "steve" })