# Synonyms result scoring

**URL:** <https://discuss.elastic.co/t/synonyms-result-scoring/152523>\
**Category:** Elasticsearch\
**Created:** [October 15, 2018, 3:18pm UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523 "2018-10-15T15:18:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bilal](https://avatars.discourse-cdn.com/v4/letter/b/3ab097/32.png) [@Bilal](https://discuss.elastic.co/u/Bilal)\
**Post date:** [October 15, 2018, 3:18pm UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523/1 "2018-10-15T15:18:52Z")

</div>

I'm reading [this article](https://opensourceconnections.com/blog/2016/12/02/solr-elasticsearch-synonyms-better-patterns-keyphrases/) about Patterns for Synonyms in Elasticsearch and I have some questions about the results that I got, here is the mappings and settings I used:

```
PUT wheat_syn
{
  "mappings": {
    "wheat": {
      "properties": {
        "description": {
          "type": "text",
          "analyzer": "syn_text",
          "fields": {
            "keyword": {
             "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  },
  "settings": {
    "analysis": {
      "filter": {
        "autophrase_syn": {
          "type": "synonym",
          "synonyms": ["triticum aestivum => triticum_aestivum",
                       "bread wheat => bread_wheat"]
        },
        "wheat_syn": {
          "type": "synonym",
          "tokenizer": "keyword",
          "synonyms": ["triticum_aestivum, bread_wheat, wheat"]
        }
      },
      "analyzer": {
        "syn_text": {
          "tokenizer": "standard",
          "filter": ["lowercase", "autophrase_syn", "wheat_syn"]
        }
      }
    }
  }
}

```

The Documents:

```
PUT wheat_syn/wheat/_bulk
{ "index" : { "_id" : "1" } }
{ "description": "Wheat is a grass widely cultivated for its seed, a cereal grain which is a worldwide staple food." }
{ "index" : { "_id" : "2" } }
{ "description": "The scientific name is Triticum aestivum." }
{ "index" : { "_id" : "3" } }
{ "description": "bread wheat is good for health." }

```

The query:

```
GET wheat_syn/wheat/_search
{
  "query": {
    "match": {
      "description": "wheat"
    }
  }
}

```

After executing the query, I got the following result:

```
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 0.48155478,
    "hits": [
      {
        "_index": "wheat_syn",
        "_type": "wheat",
        "_id": "2",
        "_score": 0.48155478,
        "_source": {
          "description": "The scientific name is Triticum aestivum."
        }
      },
      {
        "_index": "wheat_syn",
        "_type": "wheat",
        "_id": "3",
        "_score": 0.48155478,
        "_source": {
          "description": "bread wheat is good for health."
        }
      },
      {
        "_index": "wheat_syn",
        "_type": "wheat",
        "_id": "1",
        "_score": 0.46197122,
        "_source": {
          "description": "Wheat is a grass widely cultivated for its seed, a cereal grain which is a worldwide staple food."
        }
      }
    ]
  }
}

```

Now, my questions are:

1. I was expecting to get the sentence `Wheat is a grass widely cultivated for its seed, a cereal grain which is a worldwide staple food` first since the user was looking for this word, why isn't the case ?
2. Why there is a difference in the score and if it's depend on the position of the queried sentence/word in the description field, the third sentence in the results should be first right ? (this is a simple example, the more documents I add the higher difference of score is).

Thank you !

---

<div class="post-metadata">

**Author:** ![abdon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/abdon/32/9195_2.png) [@abdon](https://discuss.elastic.co/u/abdon)\
**Post date:** [October 15, 2018, 4:34pm UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523/2 "2018-10-15T16:34:32Z")

</div>

Great questions!

1. Synonyms score the same as an exact match. There is no automatic preference for exact matches.
2. The length of a field is an important factor that determines the score: shorter fields score higher than longer fields. What you're seeing is that the documents with a shorter field (6 terms) score higher than the document with a longer field (18 terms).

If you want to understand how a score is calculated, you can add `"explain": true` to a search request, and Elasticsearch will tell you exactly how the score for each hit was calculated:

```auto
GET wheat_syn/wheat/_search
{
  "explain": true, 
  "query": {
    "match": {
      "description": "wheat"
    }
  }
}

```

Some suggestions: if you are looking at scores for a small dataset like this, consider creating the index with one shard (instead of the default 5). Otherwise the scoring may be unexpected as explained [here](https://www.elastic.co/guide/en/elasticsearch/guide/current/relevance-is-broken.html).

Also, consider indexing the data twice: once with synonyms and once without synonyms. You can do that by using [multi-fields](https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html). Your index creation command would become:

```auto
PUT wheat_syn
{
  "mappings": {
    "wheat": {
      "properties": {
        "description": {
          "type": "text",
          "fields": {
            "synonyms": {
              "type": "text",
              "analyzer": "syn_text"
            },
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  },
  "settings": {
    "number_of_shards": 1,
    "analysis": {
      "filter": {
        "autophrase_syn": {
          "type": "synonym",
          "synonyms": [
            "triticum aestivum => triticum_aestivum",
            "bread wheat => bread_wheat"
          ]
        },
        "wheat_syn": {
          "type": "synonym",
          "tokenizer": "keyword",
          "synonyms": [
            "triticum_aestivum, bread_wheat, wheat"
          ]
        }
      },
      "analyzer": {
        "syn_text": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autophrase_syn",
            "wheat_syn"
          ]
        }
      }
    }
  }
}

```

Now, you can use a `bool` query to search simultaneously with and without synonyms:

```auto
GET wheat_syn/wheat/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description.synonyms": "wheat"
          }
        }
      ],
      "should": [
        {
          "match": {
            "description": {
              "query": "wheat"
            }
          }
        }
      ]
    }
  }
}

```

Those documents that contain the exact term are the only ones that match the `should` clause (which does not use synonyms). As a result, those docs will get a higher score and rank at the top of the results.

Synonyms can be tricky to set up correctly. We will soon launch an [on-demand training course about synonyms](https://www.elastic.co/training/specializations/elasticsearch-advanced-search/improving-search-with-synonyms) that covers topics like this.

---

<div class="post-metadata">

**Author:** ![Bilal](https://avatars.discourse-cdn.com/v4/letter/b/3ab097/32.png) [@Bilal](https://discuss.elastic.co/u/Bilal)\
**Post date:** [October 16, 2018, 9:51am UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523/3 "2018-10-16T09:51:56Z")

</div>

Thank you for the detailed answer, the example you provided worked perfectly, now I understand why I had this unexpected results.

In the link you provided ([Relevence is Broken !](https://www.elastic.co/guide/en/elasticsearch/guide/current/relevance-is-broken.html#relevance-is-broken)) it says:

> In practice, this is not a problem. The differences between local and global IDF diminish the more documents that you add to the index. With real-world volumes of data, the local IDFs soon even out. The problem is not that relevance is broken but that there is too little data.

Which explains a lot ! so in case I have a large dataset, Can your suggestions still be applied ? I mean, I can increase the number of shards and index my data twice without problems ? are there anythings that I shall take into account ?

---

<div class="post-metadata">

**Author:** ![abdon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/abdon/32/9195_2.png) [@abdon](https://discuss.elastic.co/u/abdon)\
**Post date:** [October 16, 2018, 10:16am UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523/4 "2018-10-16T10:16:45Z")

</div>

Yes, all of this should scale to however much data you have, and however many shards you have. I was just pointing out that with just three documents it does not make sense to have more than one shard. 🙂

---

<div class="post-metadata">

**Author:** ![softwaredoug](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/softwaredoug/32/22681_2.png) [@softwaredoug](https://discuss.elastic.co/u/softwaredoug)\
**Post date:** [November 10, 2018, 2:02pm UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523/5 "2018-11-10T14:02:53Z")

</div>

> [@abdon](#):
>
> - Synonyms score the same as an exact match. There is no automatic preference for exact matches.

Just one note, this is a good default. But it's not always a good idea to assume that synonyms should be scored as equivalent. There's a set of practices that have built up in the search relevance community around using synonyms for a variety of reasons, including expansion to broadening terms which people want to score lower.

I've put together a PR to make this behavior configurable in match / multi\_match queries (similar to a Solr patch accepted a while back - which makes this behavior configurable)

> <https://github.com/elastic/elasticsearch/pull/35422>
>
> In Lucene, SynonymQuery became the default behavior for single term synonym quer…ies, which ES 6.0 inherited. While this is a good default, it interferes with other legitimate uses of synonyms. You don't always want to blend document frequencies of the terms.
> 
> It's common to want to expand a term to a broadening term, but maintaining the specificity of the original term. (ie \`jeans =\> jeans, trousers\`). I and others have written about \[these techniques\](https://opensourceconnections.com/blog/2016/12/23/elasticsearch-synonyms-patterns-taxonomies/) for implementing hierarchical vocabularies. In these cases blending ends up doing more harm, so this PR makes this behavior configurable.
> 
> This PR introduces an option to the match query, \`synonym\_query\_style\` which can have the values \`blended\` (default), \`most\_terms\`, or \`best\_terms\`. 
> 
> \`\`\`
> {
> "match": {
> "text": {
> "query": "blue jeans",
> "synonym\_query\_style": "most\_terms"
> }
> }
> }
> \`\`\`
> 
> with a synonym file \`jeans, trousers\` would turn into a search: \`text:jeans text:trousers\`. This is basically the pre 6.0 behavior.
> 
> Using \`best\_terms\` changes the synonym query to a dismax \`text:jeans | text:trousers\` which tends to ignore the broader term in the narrower term is present.
> 
> One note on this PR, 
> \- tests seem to be failing locally for me for unrelated functionality (transport client stuff...)
> \- any feedback on where to place a test is greatly appreciated. I looked for how other match query options were tested and did not find anything.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [December 8, 2018, 2:02pm UTC](https://discuss.elastic.co/t/synonyms-result-scoring/152523/6 "2018-12-08T14:02:54Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
