1

I have an Elasticsearch database with several fields that can include name information and am attempting to search it like so:

from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search

client = Elasticsearch()
s = Search(using=client, index="names")
query = 'smith'
fields = ['name1', 'name2']

results = s.query("multi_match", query=query, fields=fields, fuzziness='AUTO')

for hit in results.scan():
    print(hit.meta.score)

The results are:

None
None
None
...

However, if I structure it manually:

results = client.search(index="names",
    body={"size": 100, "query":{
        "multi_match": {
            "query": query, "fields": fields, "fuzziness": 'AUTO'
        }
    }
})

My results are:

{'_index': 'names', '_type': 'Name1', '_id': '1MtYSW4BXryTHXwQ1xBS', '_score': 14.226202, '_source': {...}
{'_index': 'names', '_type': 'Name1', '_id': 'N8tZSW4BXryTHXwQHBfw', '_score': 14.226202, '_source': {...}
{'_index': 'names', '_type': 'Name1', '_id': '8MtZSW4BXryTHXwQeR-i', '_score': 14.226202, '_source': {...}

I would prefer to use elasticsearch-dsl if possible, but I need the score information.

tufelkinder
  • 1,176
  • 1
  • 15
  • 37

4 Answers4

5

The first version of the code is not equivalent to the second version of the code. Instead of executing a query, the first version uses Scroll API (elasticsearch.helpers.scan).

Search.query() method build or extend a search object, not send a query to elasticsearch. So the following line of the code is misleading:

results = s.query("multi_match", query=query, fields=fields, fuzziness='AUTO')

It should be like this:

# execute() added at the end
results = s.query("multi_match", query=query, fields=fields, fuzziness='AUTO').execute()
# scan() removed 
for hit in results:
    print(hit.meta.score)
zbusia
  • 571
  • 2
  • 7
1

Try this:

from elasticsearch_dsl.query import MultiMatch
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search

client = Elasticsearch()
s = Search(using=client, index="names")
query = 'smith'
fields = ['name1', 'name2']

query_multi = 
MultiMatch(query=query,fields=fields,fuzziness='AUTO')

r = s.query(query_multi)
results = r.execute()
for hit in results:
    print(hit.meta.score)
Assael Azran
  • 2,863
  • 1
  • 9
  • 13
1

Try this:

s = s.params(preserve_order=True).sort("_score")

then scan can return score.

Scan will fill sort with ['_doc'] by default, this is why it wouldn't return a score.

wuerfelfreak
  • 2,363
  • 1
  • 14
  • 29
Raise
  • 11
  • 1
0

Try like this instead:

results = s.query("multi_match", query=query, fields=fields, fuzziness='AUTO')
for hit in results["hits"]["hits"]:
    print(hit._score)
Val
  • 207,596
  • 13
  • 358
  • 360