# inconsistent document scores using search\_type=dfs\_query\_then\_fetch (how do the \_score and \_explanation.value fields relate?)

**URL:** <https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151>\
**Category:** Elasticsearch\
**Created:** [December 13, 2011, 10:13pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151 "2011-12-13T22:13:31Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![cole](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@cole](https://discuss.elastic.co/u/cole)\
**Post date:** [December 13, 2011, 10:13pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/1 "2011-12-13T22:13:31Z")

</div>

Hello,

I'm running into issues with inconsistently scored documents between  
different index configurations, and I think may be misunderstanding  
some of the basics of how scores are calculated. Repro details are  
below, but my basic question is how a hit's \_score relates to its  
\_explanation.value (provided when "explain" : true is set in the  
query). I understand scores are by default calculated within each  
shard, but I thought passing search\_type=dfs\_query\_then\_fetch would  
lead to the calculation of globally "correct" scores.

Repro steps:

[start with empty index, configured with 1 or 2 shards as called out  
below]  
curl -XPUT [http://localhost:9200/index/mytype/1](http://localhost:9200/index/mytype/1) -d '{ "name" : "Foo  
Bar" }'  
curl -XPUT [http://localhost:9200/index/mytype/2](http://localhost:9200/index/mytype/2) -d '{ "name" : "Foo  
Zip" }'  
curl -XPUT [http://localhost:9200/index/mytype/3](http://localhost:9200/index/mytype/3) -d '{ "name" : "Zap  
Foo" }'  
curl -XPUT [http://localhost:9200/index/mytype/4](http://localhost:9200/index/mytype/4) -d '{ "name" :  
"Something Else" }'

When the index is configure to use one shard, I get the following  
results as expected. Note this is the desired result ("Foo Bar" is  
scored highest and "Foo Zip" and "Zap Foo" are tied for second best).

curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
{  
"took" : 40,  
"timed\_out" : false,  
"\_shards" : {  
"total" : 1,  
"successful" : 1,  
"failed" : 0  
},  
"hits" : {  
"total" : 3,  
"max\_score" : 1.2290028,  
"hits" : [ {  
"\_shard" : 0,  
...  
"\_id" : "1",  
"\_score" : 1.2290028, "\_source" : { "name" : "Foo Bar" },  
"\_explanation" : {  
"value" : 1.229003,  
...  
}, {  
"\_shard" : 0,  
...  
"\_id" : "2",  
"\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
"\_explanation" : {  
"value" : 0.15891947,  
...  
}, {  
"\_shard" : 0,  
...  
"\_id" : "3",  
"\_score" : 0.15891947, "\_source" : { "name" : "Zap Foo" },  
"\_explanation" : {  
"value" : 0.15891947,  
...  
} ]  
}  
}

When the index is configured to use two shards, I get the following  
results as expected. Note these results aren't desirable since "Zap  
Foo" is being scored lower than "Foo Zip", but they're expected since  
the documents are stored in different shards and  
search\_type=dfs\_query\_then\_fetch isn't specified.

curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
{  
"took" : 2,  
"timed\_out" : false,  
"\_shards" : {  
"total" : 2,  
"successful" : 2,  
"failed" : 0  
},  
"hits" : {  
"total" : 3,  
"max\_score" : 0.72711754,  
"hits" : [ {  
"\_shard" : 0,  
...  
"\_id" : "1",  
"\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
"\_explanation" : {  
"value" : 0.7271175,  
...  
}, {  
"\_shard" : 1,  
...  
"\_id" : "2",  
"\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
"\_explanation" : {  
"value" : 0.15891947,  
...  
}, {  
"\_shard" : 0,  
...  
"\_id" : "3",  
"\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
"\_explanation" : {  
"value" : 0.09494675,  
...  
} ]  
}  
}

In the two previous cases, \_explanation.value matches \_score for each  
hit, which is what I'd expect from the \_explanation data structure.  
Now, with the 2-shard index again, I'd expect specifying  
search\_type=dfs\_query\_then\_fetch would provide me with the desired  
results of "Foo Bar" matching highest and "Foo Zip" and "Zap Foo"  
tying for second best.

curl -XGET 'localhost:9200/index/mytype/\_search?  
pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'

{  
"took" : 2,  
"timed\_out" : false,  
"\_shards" : {  
"total" : 2,  
"successful" : 2,  
"failed" : 0  
},  
"hits" : {  
"total" : 3,  
"max\_score" : 0.72711754,  
"hits" : [ {  
"\_shard" : 0,  
...  
"\_id" : "1",  
"\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
"\_explanation" : {  
"value" : 1.229003,  
...  
}, {  
"\_shard" : 1,  
...  
"\_id" : "2",  
"\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
"\_explanation" : {  
"value" : 0.15891947,  
...  
}, {  
"\_shard" : 0,  
...  
"\_id" : "3",  
"\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
"\_explanation" : {  
"value" : 0.15891947,  
...  
} ]  
}  
}

Note in this case \_explanation.value does not match \_score for hits 1  
and 3, and \_score for hits 2 and 3 differ even though  
\_explanation.value matches. What is causing \_explanation.value to  
change for the final \_score field? If someone could point out to me  
what I'm missing about the relationship between \_score and  
\_explanation.value, I'd very much appreciate it.

Ideally, the results from my search system would be consistent between  
indexing runs using generated document IDs (or, stated differently,  
the shard allocation would not affect document scoring). Is that  
achievable?

Thanks,  
Cole

---

<div class="post-metadata">

**Author:** ![kimchy](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/kimchy/32/44952_2.png) [@kimchy](https://discuss.elastic.co/u/kimchy)\
**Post date:** [December 13, 2011, 10:21pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/2 "2011-12-13T22:21:53Z")

</div>

I need to double check, but the explanation part will not take the dfs  
scoring into account when it shows it (so it will still show shard level  
scoring), but the \_score will.

On Wed, Dec 14, 2011 at 12:13 AM, cole [cole.rottweiler@gmail.com](mailto:cole.rottweiler@gmail.com) wrote:

> Hello,
> 
> I'm running into issues with inconsistently scored documents between  
> different index configurations, and I think may be misunderstanding  
> some of the basics of how scores are calculated. Repro details are  
> below, but my basic question is how a hit's \_score relates to its  
> \_explanation.value (provided when "explain" : true is set in the  
> query). I understand scores are by default calculated within each  
> shard, but I thought passing search\_type=dfs\_query\_then\_fetch would  
> lead to the calculation of globally "correct" scores.
> 
> Repro steps:
> 
> [start with empty index, configured with 1 or 2 shards as called out  
> below]  
> curl -XPUT [http://localhost:9200/index/mytype/1](http://localhost:9200/index/mytype/1) -d '{ "name" : "Foo  
> Bar" }'  
> curl -XPUT [http://localhost:9200/index/mytype/2](http://localhost:9200/index/mytype/2) -d '{ "name" : "Foo  
> Zip" }'  
> curl -XPUT [http://localhost:9200/index/mytype/3](http://localhost:9200/index/mytype/3) -d '{ "name" : "Zap  
> Foo" }'  
> curl -XPUT [http://localhost:9200/index/mytype/4](http://localhost:9200/index/mytype/4) -d '{ "name" :  
> "Something Else" }'
> 
> When the index is configure to use one shard, I get the following  
> results as expected. Note this is the desired result ("Foo Bar" is  
> scored highest and "Foo Zip" and "Zap Foo" are tied for second best).
> 
> curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> {  
> "took" : 40,  
> "timed\_out" : false,  
> "\_shards" : {  
> "total" : 1,  
> "successful" : 1,  
> "failed" : 0  
> },  
> "hits" : {  
> "total" : 3,  
> "max\_score" : 1.2290028,  
> "hits" : [ {  
> "\_shard" : 0,  
> ...  
> "\_id" : "1",  
> "\_score" : 1.2290028, "\_source" : { "name" : "Foo Bar" },  
> "\_explanation" : {  
> "value" : 1.229003,  
> ...  
> }, {  
> "\_shard" : 0,  
> ...  
> "\_id" : "2",  
> "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> "\_explanation" : {  
> "value" : 0.15891947,  
> ...  
> }, {  
> "\_shard" : 0,  
> ...  
> "\_id" : "3",  
> "\_score" : 0.15891947, "\_source" : { "name" : "Zap Foo" },  
> "\_explanation" : {  
> "value" : 0.15891947,  
> ...  
> } ]  
> }  
> }
> 
> When the index is configured to use two shards, I get the following  
> results as expected. Note these results aren't desirable since "Zap  
> Foo" is being scored lower than "Foo Zip", but they're expected since  
> the documents are stored in different shards and  
> search\_type=dfs\_query\_then\_fetch isn't specified.
> 
> curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> {  
> "took" : 2,  
> "timed\_out" : false,  
> "\_shards" : {  
> "total" : 2,  
> "successful" : 2,  
> "failed" : 0  
> },  
> "hits" : {  
> "total" : 3,  
> "max\_score" : 0.72711754,  
> "hits" : [ {  
> "\_shard" : 0,  
> ...  
> "\_id" : "1",  
> "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> "\_explanation" : {  
> "value" : 0.7271175,  
> ...  
> }, {  
> "\_shard" : 1,  
> ...  
> "\_id" : "2",  
> "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> "\_explanation" : {  
> "value" : 0.15891947,  
> ...  
> }, {  
> "\_shard" : 0,  
> ...  
> "\_id" : "3",  
> "\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
> "\_explanation" : {  
> "value" : 0.09494675,  
> ...  
> } ]  
> }  
> }
> 
> In the two previous cases, \_explanation.value matches \_score for each  
> hit, which is what I'd expect from the \_explanation data structure.  
> Now, with the 2-shard index again, I'd expect specifying  
> search\_type=dfs\_query\_then\_fetch would provide me with the desired  
> results of "Foo Bar" matching highest and "Foo Zip" and "Zap Foo"  
> tying for second best.
> 
> curl -XGET 'localhost:9200/index/mytype/\_search?  
> pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> {"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'
> 
> {  
> "took" : 2,  
> "timed\_out" : false,  
> "\_shards" : {  
> "total" : 2,  
> "successful" : 2,  
> "failed" : 0  
> },  
> "hits" : {  
> "total" : 3,  
> "max\_score" : 0.72711754,  
> "hits" : [ {  
> "\_shard" : 0,  
> ...  
> "\_id" : "1",  
> "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> "\_explanation" : {  
> "value" : 1.229003,  
> ...  
> }, {  
> "\_shard" : 1,  
> ...  
> "\_id" : "2",  
> "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> "\_explanation" : {  
> "value" : 0.15891947,  
> ...  
> }, {  
> "\_shard" : 0,  
> ...  
> "\_id" : "3",  
> "\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
> "\_explanation" : {  
> "value" : 0.15891947,  
> ...  
> } ]  
> }  
> }
> 
> Note in this case \_explanation.value does not match \_score for hits 1  
> and 3, and \_score for hits 2 and 3 differ even though  
> \_explanation.value matches. What is causing \_explanation.value to  
> change for the final \_score field? If someone could point out to me  
> what I'm missing about the relationship between \_score and  
> \_explanation.value, I'd very much appreciate it.
> 
> Ideally, the results from my search system would be consistent between  
> indexing runs using generated document IDs (or, stated differently,  
> the shard allocation would not affect document scoring). Is that  
> achievable?
> 
> Thanks,  
> Cole

---

<div class="post-metadata">

**Author:** ![cole](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@cole](https://discuss.elastic.co/u/cole)\
**Post date:** [December 13, 2011, 11:01pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/3 "2011-12-13T23:01:41Z")

</div>

If \_explanation.value was still showing shard-level scoring, wouldn't  
the \_explanation.value fields be the same between the second and third  
example I gave (the 2-shard example without search\_type specified vs.  
the 2-shard example with search\_type=dfs\_query\_then\_fetch)? In the  
second example, \_explanation.value is different for hits 2 and 3  
(which is what I was attempting to "fix"). In the third example,  
\_explanation.value is the same for hits 2 and 3, which leads me to  
believe the dfs scoring is being reflected in \_explanation.value.

-cole

On Dec 13, 2:21 pm, Shay Banon [kim...@gmail.com](mailto:kim...@gmail.com) wrote:

> I need to double check, but the explanation part will not take the dfs  
> scoring into account when it shows it (so it will still show shard level  
> scoring), but the \_score will.
> 
> On Wed, Dec 14, 2011 at 12:13 AM, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > Hello,
> 
> > I'm running into issues with inconsistently scored documents between  
> > different index configurations, and I think may be misunderstanding  
> > some of the basics of how scores are calculated. Repro details are  
> > below, but my basic question is how a hit's \_score relates to its  
> > \_explanation.value (provided when "explain" : true is set in the  
> > query). I understand scores are by default calculated within each  
> > shard, but I thought passing search\_type=dfs\_query\_then\_fetch would  
> > lead to the calculation of globally "correct" scores.
> 
> > Repro steps:
> 
> > [start with empty index, configured with 1 or 2 shards as called out  
> > below]  
> > curl -XPUThttp://localhost:9200/index/mytype/1-d '{ "name" : "Foo  
> > Bar" }'  
> > curl -XPUThttp://localhost:9200/index/mytype/2-d '{ "name" : "Foo  
> > Zip" }'  
> > curl -XPUThttp://localhost:9200/index/mytype/3-d '{ "name" : "Zap  
> > Foo" }'  
> > curl -XPUThttp://localhost:9200/index/mytype/4-d '{ "name" :  
> > "Something Else" }'
> 
> > When the index is configure to use one shard, I get the following  
> > results as expected. Note this is the desired result ("Foo Bar" is  
> > scored highest and "Foo Zip" and "Zap Foo" are tied for second best).
> 
> > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > {  
> > "took" : 40,  
> > "timed\_out" : false,  
> > "\_shards" : {  
> > "total" : 1,  
> > "successful" : 1,  
> > "failed" : 0  
> > },  
> > "hits" : {  
> > "total" : 3,  
> > "max\_score" : 1.2290028,  
> > "hits" : [ {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 1.2290028, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 1.229003,  
> > ...  
> > }, {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > "\_explanation" : {  
> > "value" : 0.15891947,  
> > ...  
> > }, {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.15891947, "\_source" : { "name" : "Zap Foo" },  
> > "\_explanation" : {  
> > "value" : 0.15891947,  
> > ...  
> > } ]  
> > }  
> > }
> 
> > When the index is configured to use two shards, I get the following  
> > results as expected. Note these results aren't desirable since "Zap  
> > Foo" is being scored lower than "Foo Zip", but they're expected since  
> > the documents are stored in different shards and  
> > search\_type=dfs\_query\_then\_fetch isn't specified.
> 
> > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > {  
> > "took" : 2,  
> > "timed\_out" : false,  
> > "\_shards" : {  
> > "total" : 2,  
> > "successful" : 2,  
> > "failed" : 0  
> > },  
> > "hits" : {  
> > "total" : 3,  
> > "max\_score" : 0.72711754,  
> > "hits" : [ {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 0.7271175,  
> > ...  
> > }, {  
> > "\_shard" : 1,  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > "\_explanation" : {  
> > "value" : 0.15891947,  
> > ...  
> > }, {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
> > "\_explanation" : {  
> > "value" : 0.09494675,  
> > ...  
> > } ]  
> > }  
> > }
> 
> > In the two previous cases, \_explanation.value matches \_score for each  
> > hit, which is what I'd expect from the \_explanation data structure.  
> > Now, with the 2-shard index again, I'd expect specifying  
> > search\_type=dfs\_query\_then\_fetch would provide me with the desired  
> > results of "Foo Bar" matching highest and "Foo Zip" and "Zap Foo"  
> > tying for second best.
> 
> > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > {"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'
> 
> > {  
> > "took" : 2,  
> > "timed\_out" : false,  
> > "\_shards" : {  
> > "total" : 2,  
> > "successful" : 2,  
> > "failed" : 0  
> > },  
> > "hits" : {  
> > "total" : 3,  
> > "max\_score" : 0.72711754,  
> > "hits" : [ {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 1.229003,  
> > ...  
> > }, {  
> > "\_shard" : 1,  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > "\_explanation" : {  
> > "value" : 0.15891947,  
> > ...  
> > }, {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
> > "\_explanation" : {  
> > "value" : 0.15891947,  
> > ...  
> > } ]  
> > }  
> > }
> 
> > Note in this case \_explanation.value does not match \_score for hits 1  
> > and 3, and \_score for hits 2 and 3 differ even though  
> > \_explanation.value matches. What is causing \_explanation.value to  
> > change for the final \_score field? If someone could point out to me  
> > what I'm missing about the relationship between \_score and  
> > \_explanation.value, I'd very much appreciate it.
> 
> > Ideally, the results from my search system would be consistent between  
> > indexing runs using generated document IDs (or, stated differently,  
> > the shard allocation would not affect document scoring). Is that  
> > achievable?
> 
> > Thanks,  
> > Cole

---

<div class="post-metadata">

**Author:** ![cole](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@cole](https://discuss.elastic.co/u/cole)\
**Post date:** [December 15, 2011, 7:54pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/4 "2011-12-15T19:54:06Z")

</div>

Hi Shay,

I've made some progress in debugging the issue I'm seeing with  
dfs\_query\_then\_fetch (the search\_type=dfs\_query\_then\_fetch behavior  
appears to have changed between v0.16.4 and v0.17.0 -- see the full  
details of my investigation below).

A simpler example than the one I originally gave is the following:

- Create a fresh index configured to use 2 shards.

- Add a few simple documents:  
curl -XPUT [http://localhost:9200/index/mytype/1](http://localhost:9200/index/mytype/1) -d '{ "name" : "Foo  
Bar" }'  
curl -XPUT [http://localhost:9200/index/mytype/2](http://localhost:9200/index/mytype/2) -d '{ "name" :  
"Foo" }'  
curl -XPUT [http://localhost:9200/index/mytype/3](http://localhost:9200/index/mytype/3) -d '{ "name" :  
"Foo" }'

- Query using the default search\_type:  
curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
'{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}}'  
{  
...  
"hits" : {  
...  
"hits" : [ {  
...  
"\_id" : "1",  
"\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
}, {  
...  
"\_id" : "3",  
"\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
}, {  
...  
"\_id" : "2",  
"\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
} ]  
}  
}

- Query using search\_type=dfs\_query\_then\_fetch (note the results are  
exactly the same as the first query):  
curl -XGET 'localhost:9200/index/mytype/\_search?  
pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
{"must":[{"text":{"name":"Foo Bar"}}]}}}'  
{  
...  
"hits" : {  
...  
"hits" : [ {  
...  
"\_id" : "1",  
"\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
}, {  
...  
"\_id" : "3",  
"\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
}, {  
...  
"\_id" : "2",  
"\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
} ]  
}  
}

- Query with "explain":true using the default search\_type and note  
\_explanation.value matches \_score for each result.  
curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
'{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}},  
"explain":"true"}'  
{  
...  
"hits" : {  
...  
"hits" : [ {  
"\_shard" : 0,  
...  
"\_id" : "1",  
"\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
"\_explanation" : {  
"value" : 0.7271175,  
...  
}, {  
"\_shard" : 0,  
...  
"\_id" : "3",  
"\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
"\_explanation" : {  
"value" : 0.1519148,  
...  
}, {  
"\_shard" : 1,  
...  
"\_id" : "2",  
"\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
"\_explanation" : {  
"value" : 0.04500804,  
...  
} ]  
}  
}

- Query with "explain":true using search\_type=def\_query\_then\_fetch and  
note the following:

It looks like search\_type=dfs\_query\_then\_fetch is being taken into  
account in the score calculation (expressed in \_explanation.value),  
but the shard-level score is actually being returned for \_score.

Note I've been using v0.18.5 for all of these examples (apologies for  
not mentioning that earlier). Using an identical set of repro steps,  
I see the same issue in v0.17.0, but I don't see the same issue in  
v0.16.4. With v0.16.4, I get the following:

- Query with "explain":true using the default search\_type and note  
\_explanation.value matches \_score for each result.  
curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
'{"query":{"bool":{"must":[{"text":{"name":"Foo  
Bar"}}]}},"explain":true}'  
{  
...  
"hits" : {  
...  
"hits" : [ {  
...  
"\_id" : "1",  
"\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
"\_explanation" : {  
"value" : 0.7271175,  
...  
}, {  
...  
"\_id" : "3",  
"\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
"\_explanation" : {  
"value" : 0.1519148,  
...  
}, {  
...  
"\_id" : "2",  
"\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
"\_explanation" : {  
"value" : 0.04500804,  
...  
} ]  
}  
}

- Query with "explain":true using search\_type=def\_query\_then\_fetch and  
note the following:

It looks like something changed between v0.16.4 and v0.17.0 that  
caused \_score to not be set to \_explanation.value, and it looks like  
\_explanation.value is taking the dfs portion of the search into  
account. Can I assume the behavior in v0.16.4 is correct? Or was the  
scoring behavior intentionally changed in v0.17.0? I'll try to find  
the actual code change in the elasticsearch that caused this (I'd  
appreciate any pointers you may have since I'm not familiar with the  
codebase).

Thanks,  
Cole

On Dec 13, 3:01 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:

> If \_explanation.value was still showing shard-level scoring, wouldn't  
> the \_explanation.value fields be the same between the second and third  
> example I gave (the 2-shard example without search\_type specified vs.  
> the 2-shard example with search\_type=dfs\_query\_then\_fetch)? In the  
> second example, \_explanation.value is different for hits 2 and 3  
> (which is what I was attempting to "fix"). In the third example,  
> \_explanation.value is the same for hits 2 and 3, which leads me to  
> believe the dfs scoring is being reflected in \_explanation.value.
> 
> -cole
> 
> On Dec 13, 2:21 pm, Shay Banon [kim...@gmail.com](mailto:kim...@gmail.com) wrote:
> 
> > I need to double check, but the explanation part will not take the dfs  
> > scoring into account when it shows it (so it will still show shard level  
> > scoring), but the \_score will.
> 
> > On Wed, Dec 14, 2011 at 12:13 AM, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> > 
> > > Hello,
> 
> > > I'm running into issues with inconsistently scored documents between  
> > > different index configurations, and I think may be misunderstanding  
> > > some of the basics of how scores are calculated. Repro details are  
> > > below, but my basic question is how a hit's \_score relates to its  
> > > \_explanation.value (provided when "explain" : true is set in the  
> > > query). I understand scores are by default calculated within each  
> > > shard, but I thought passing search\_type=dfs\_query\_then\_fetch would  
> > > lead to the calculation of globally "correct" scores.
> 
> > > Repro steps:
> 
> > > [start with empty index, configured with 1 or 2 shards as called out  
> > > below]  
> > > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > > Bar" }'  
> > > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" : "Foo  
> > > Zip" }'  
> > > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" : "Zap  
> > > Foo" }'  
> > > curl -XPUThttp://localhost:9200/index/mytype/4-d'{ "name" :  
> > > "Something Else" }'
> 
> > > When the index is configure to use one shard, I get the following  
> > > results as expected. Note this is the desired result ("Foo Bar" is  
> > > scored highest and "Foo Zip" and "Zap Foo" are tied for second best).
> 
> > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> > > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > > {  
> > > "took" : 40,  
> > > "timed\_out" : false,  
> > > "\_shards" : {  
> > > "total" : 1,  
> > > "successful" : 1,  
> > > "failed" : 0  
> > > },  
> > > "hits" : {  
> > > "total" : 3,  
> > > "max\_score" : 1.2290028,  
> > > "hits" : [ {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 1.2290028, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 1.229003,  
> > > ...  
> > > }, {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > > "\_explanation" : {  
> > > "value" : 0.15891947,  
> > > ...  
> > > }, {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.15891947, "\_source" : { "name" : "Zap Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.15891947,  
> > > ...  
> > > } ]  
> > > }  
> > > }
> 
> > > When the index is configured to use two shards, I get the following  
> > > results as expected. Note these results aren't desirable since "Zap  
> > > Foo" is being scored lower than "Foo Zip", but they're expected since  
> > > the documents are stored in different shards and  
> > > search\_type=dfs\_query\_then\_fetch isn't specified.
> 
> > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> > > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > > {  
> > > "took" : 2,  
> > > "timed\_out" : false,  
> > > "\_shards" : {  
> > > "total" : 2,  
> > > "successful" : 2,  
> > > "failed" : 0  
> > > },  
> > > "hits" : {  
> > > "total" : 3,  
> > > "max\_score" : 0.72711754,  
> > > "hits" : [ {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 0.7271175,  
> > > ...  
> > > }, {  
> > > "\_shard" : 1,  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > > "\_explanation" : {  
> > > "value" : 0.15891947,  
> > > ...  
> > > }, {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.09494675,  
> > > ...  
> > > } ]  
> > > }  
> > > }
> 
> > > In the two previous cases, \_explanation.value matches \_score for each  
> > > hit, which is what I'd expect from the \_explanation data structure.  
> > > Now, with the 2-shard index again, I'd expect specifying  
> > > search\_type=dfs\_query\_then\_fetch would provide me with the desired  
> > > results of "Foo Bar" matching highest and "Foo Zip" and "Zap Foo"  
> > > tying for second best.
> 
> > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > {"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'
> 
> > > {  
> > > "took" : 2,  
> > > "timed\_out" : false,  
> > > "\_shards" : {  
> > > "total" : 2,  
> > > "successful" : 2,  
> > > "failed" : 0  
> > > },  
> > > "hits" : {  
> > > "total" : 3,  
> > > "max\_score" : 0.72711754,  
> > > "hits" : [ {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 1.229003,  
> > > ...  
> > > }, {  
> > > "\_shard" : 1,  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > > "\_explanation" : {  
> > > "value" : 0.15891947,  
> > > ...  
> > > }, {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.09494676, "\_source" : { "name" : "Zap Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.15891947,  
> > > ...  
> > > } ]  
> > > }  
> > > }
> 
> > > Note in this case \_explanation.value does not match \_score for hits 1  
> > > and 3, and \_score for hits 2 and 3 differ even though  
> > > \_explanation.value matches. What is causing \_explanation.value to  
> > > change for the final \_score field? If someone could point out to me  
> > > what I'm missing about the relationship between \_score and  
> > > \_explanation.value, I'd very much appreciate it.
> 
> > > Ideally, the results from my search system would be consistent between  
> > > indexing runs using generated document IDs (or, stated differently,  
> > > the shard allocation would not affect document scoring). Is that  
> > > achievable?
> 
> > > Thanks,  
> > > Cole

---

<div class="post-metadata">

**Author:** ![cole](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@cole](https://discuss.elastic.co/u/cole)\
**Post date:** [December 15, 2011, 8:28pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/5 "2011-12-15T20:28:36Z")

</div>

Correction: I didn't see version 0.16.5. The behavior of  
dfs\_query\_then\_fetch is the same between v0.16.4 and v0.16.5. The  
change in behavior is between v0.16.5 and v0.17.0.

-cole

On Dec 15, 11:54 am, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:

> Hi Shay,
> 
> I've made some progress in debugging the issue I'm seeing with  
> dfs\_query\_then\_fetch (the search\_type=dfs\_query\_then\_fetch behavior  
> appears to have changed between v0.16.4 and v0.17.0 -- see the full  
> details of my investigation below).
> 
> A simpler example than the one I originally gave is the following:
> 
> - Create a fresh index configured to use 2 shards.
> 
> - Add a few simple documents:  
> curl -XPUThttp://localhost:9200/index/mytype/1-d '{ "name" : "Foo  
> Bar" }'  
> curl -XPUThttp://localhost:9200/index/mytype/2-d '{ "name" :  
> "Foo" }'  
> curl -XPUThttp://localhost:9200/index/mytype/3-d '{ "name" :  
> "Foo" }'
> 
> - Query using the default search\_type:  
> curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> {  
> ...  
> "hits" : {  
> ...  
> "hits" : [ {  
> ...  
> "\_id" : "1",  
> "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> }, {  
> ...  
> "\_id" : "3",  
> "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> }, {  
> ...  
> "\_id" : "2",  
> "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> } ]  
> }
> 
> }
> 
> - Query using search\_type=dfs\_query\_then\_fetch (note the results are  
> exactly the same as the first query):  
> curl -XGET 'localhost:9200/index/mytype/\_search?  
> pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> {"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> {  
> ...  
> "hits" : {  
> ...  
> "hits" : [ {  
> ...  
> "\_id" : "1",  
> "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> }, {  
> ...  
> "\_id" : "3",  
> "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> }, {  
> ...  
> "\_id" : "2",  
> "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> } ]  
> }
> 
> }
> 
> - Query with "explain":true using the default search\_type and note  
> \_explanation.value matches \_score for each result.  
> curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}},  
> "explain":"true"}'  
> {  
> ...  
> "hits" : {  
> ...  
> "hits" : [ {  
> "\_shard" : 0,  
> ...  
> "\_id" : "1",  
> "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> "\_explanation" : {  
> "value" : 0.7271175,  
> ...  
> }, {  
> "\_shard" : 0,  
> ...  
> "\_id" : "3",  
> "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> "\_explanation" : {  
> "value" : 0.1519148,  
> ...  
> }, {  
> "\_shard" : 1,  
> ...  
> "\_id" : "2",  
> "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> "\_explanation" : {  
> "value" : 0.04500804,  
> ...  
> } ]  
> }
> 
> }
> 
> - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> note the following:
> 
> }
> 
> It looks like search\_type=dfs\_query\_then\_fetch is being taken into  
> account in the score calculation (expressed in \_explanation.value),  
> but the shard-level score is actually being returned for \_score.
> 
> Note I've been using v0.18.5 for all of these examples (apologies for  
> not mentioning that earlier). Using an identical set of repro steps,  
> I see the same issue in v0.17.0, but I don't see the same issue in  
> v0.16.4. With v0.16.4, I get the following:
> 
> - Query with "explain":true using the default search\_type and note  
> \_explanation.value matches \_score for each result.  
> curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> '{"query":{"bool":{"must":[{"text":{"name":"Foo  
> Bar"}}]}},"explain":true}'  
> {  
> ...  
> "hits" : {  
> ...  
> "hits" : [ {  
> ...  
> "\_id" : "1",  
> "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> "\_explanation" : {  
> "value" : 0.7271175,  
> ...  
> }, {  
> ...  
> "\_id" : "3",  
> "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> "\_explanation" : {  
> "value" : 0.1519148,  
> ...  
> }, {  
> ...  
> "\_id" : "2",  
> "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> "\_explanation" : {  
> "value" : 0.04500804,  
> ...  
> } ]  
> }
> 
> }
> 
> - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> note the following:
> 
> }
> 
> It looks like something changed between v0.16.4 and v0.17.0 that  
> caused \_score to not be set to \_explanation.value, and it looks like  
> \_explanation.value is taking the dfs portion of the search into  
> account. Can I assume the behavior in v0.16.4 is correct? Or was the  
> scoring behavior intentionally changed in v0.17.0? I'll try to find  
> the actual code change in the elasticsearch that caused this (I'd  
> appreciate any pointers you may have since I'm not familiar with the  
> codebase).
> 
> Thanks,  
> Cole
> 
> On Dec 13, 3:01 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > If \_explanation.value was still showing shard-level scoring, wouldn't  
> > the \_explanation.value fields be the same between the second and third  
> > example I gave (the 2-shard example without search\_type specified vs.  
> > the 2-shard example with search\_type=dfs\_query\_then\_fetch)? In the  
> > second example, \_explanation.value is different for hits 2 and 3  
> > (which is what I was attempting to "fix"). In the third example,  
> > \_explanation.value is the same for hits 2 and 3, which leads me to  
> > believe the dfs scoring is being reflected in \_explanation.value.
> 
> > -cole
> 
> > On Dec 13, 2:21 pm, Shay Banon [kim...@gmail.com](mailto:kim...@gmail.com) wrote:
> 
> > > I need to double check, but the explanation part will not take the dfs  
> > > scoring into account when it shows it (so it will still show shard level  
> > > scoring), but the \_score will.
> 
> > > On Wed, Dec 14, 2011 at 12:13 AM, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> > > 
> > > > Hello,
> 
> > > > I'm running into issues with inconsistently scored documents between  
> > > > different index configurations, and I think may be misunderstanding  
> > > > some of the basics of how scores are calculated. Repro details are  
> > > > below, but my basic question is how a hit's \_score relates to its  
> > > > \_explanation.value (provided when "explain" : true is set in the  
> > > > query). I understand scores are by default calculated within each  
> > > > shard, but I thought passing search\_type=dfs\_query\_then\_fetch would  
> > > > lead to the calculation of globally "correct" scores.
> 
> > > > Repro steps:
> 
> > > > [start with empty index, configured with 1 or 2 shards as called out  
> > > > below]  
> > > > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > > > Bar" }'  
> > > > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" : "Foo  
> > > > Zip" }'  
> > > > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" : "Zap  
> > > > Foo" }'  
> > > > curl -XPUThttp://localhost:9200/index/mytype/4-d'{ "name" :  
> > > > "Something Else" }'
> 
> > > > When the index is configure to use one shard, I get the following  
> > > > results as expected. Note this is the desired result ("Foo Bar" is  
> > > > scored highest and "Foo Zip" and "Zap Foo" are tied for second best).
> 
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> > > > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > > > {  
> > > > "took" : 40,  
> > > > "timed\_out" : false,  
> > > > "\_shards" : {  
> > > > "total" : 1,  
> > > > "successful" : 1,  
> > > > "failed" : 0  
> > > > },  
> > > > "hits" : {  
> > > > "total" : 3,  
> > > > "max\_score" : 1.2290028,  
> > > > "hits" : [ {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 1.2290028, "\_source" : { "name" : "Foo Bar" },  
> > > > "\_explanation" : {  
> > > > "value" : 1.229003,  
> > > > ...  
> > > > }, {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.15891947, "\_source" : { "name" : "Foo Zip" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.15891947,  
> > > > ...  
> > > > }, {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.15891947, "\_source" : { "name" : "Zap Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.15891947,  
> > > > ...  
> > > > } ]  
> > > > }  
> > > > }
> 
> > > > When the index is configured to use two shards, I get the following  
> > > > results as expected. Note these
> 
> ...
> 
> read more »

---

<div class="post-metadata">

**Author:** ![cole](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@cole](https://discuss.elastic.co/u/cole)\
**Post date:** [December 16, 2011, 12:01am UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/6 "2011-12-16T00:01:05Z")

</div>

Commit 882ccf32c826eed14950ba64c76df656ef45c01e caused the change in  
dfs\_query\_then\_fetch behavior. Specifically, this following change is  
responsible:

diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/  
search/internal/ContextIndexSearcher.java b/modules/elasticsearch/src/  
main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java  
index f09683f..9c1149b 100644  
--- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/  
internal/ContextIndexSearcher.java  
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/  
internal/ContextIndexSearcher.java  
@@ -131,10 +131,11 @@ public class ContextIndexSearcher extends  
ExtendedIndexSearcher {  
}

```
 @Override public Weight createNormalizedWeight(Query query)

```

throws IOException {

- 

```
   if (dfSource == null) {

```

- 

```
       return super.createNormalizedWeight(query);

```

- 

```
   // if its the main query, use we have dfs data, only then do

```

it

- 

```
   if (dfSource != null && (query == searchContext.query() ||

```

query == searchContext.parsedQuery().query())) {

- 

```
       return dfSource.createNormalizedWeight(query);
   }

```

- 

```
   return dfSource.createNormalizedWeight(query);

```

- 

```
   return super.createNormalizedWeight(query);

```

}

Shay, can you shed some light on that change (the commit message was  
"only use dfs data on main query executed")? If I change the code  
back on the v0.18.5 tag, I get the dfs\_query\_then\_fetch behavior I  
expect, but I'm assuming the code you added affects more complex query  
types (parent-child queries by the looks of the unit test added in the  
same commit). Did you intend for the change to also affect the basic  
dfs\_query\_then\_fetch behavior?

Thanks,  
Cole

On Dec 15, 12:28 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:

> Correction: I didn't see version 0.16.5. The behavior of  
> dfs\_query\_then\_fetch is the same between v0.16.4 and v0.16.5. The  
> change in behavior is between v0.16.5 and v0.17.0.
> 
> -cole
> 
> On Dec 15, 11:54 am, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > Hi Shay,
> 
> > I've made some progress in debugging the issue I'm seeing with  
> > dfs\_query\_then\_fetch (the search\_type=dfs\_query\_then\_fetch behavior  
> > appears to have changed between v0.16.4 and v0.17.0 -- see the full  
> > details of my investigation below).
> 
> > A simpler example than the one I originally gave is the following:
> 
> > - Create a fresh index configured to use 2 shards.
> 
> > - Add a few simple documents:  
> > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > Bar" }'  
> > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" :  
> > "Foo" }'  
> > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" :  
> > "Foo" }'
> 
> > - Query using the default search\_type:  
> > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> > {  
> > ...  
> > "hits" : {  
> > ...  
> > "hits" : [ {  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> > }, {  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> > }, {  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> > } ]  
> > }
> 
> > }
> 
> > - Query using search\_type=dfs\_query\_then\_fetch (note the results are  
> > exactly the same as the first query):  
> > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > {"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> > {  
> > ...  
> > "hits" : {  
> > ...  
> > "hits" : [ {  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> > }, {  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> > }, {  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> > } ]  
> > }
> 
> > }
> 
> > - Query with "explain":true using the default search\_type and note  
> > \_explanation.value matches \_score for each result.  
> > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}},  
> > "explain":"true"}'  
> > {  
> > ...  
> > "hits" : {  
> > ...  
> > "hits" : [ {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 0.7271175,  
> > ...  
> > }, {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.1519148,  
> > ...  
> > }, {  
> > "\_shard" : 1,  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.04500804,  
> > ...  
> > } ]  
> > }
> 
> > }
> 
> > - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> > note the following:
> > - \_explanation.value differ from \_score
> > - \_explanation.value differs from \_explanation.value in the default  
> > search\_type query
> > - \_score matches \_score from the default search\_type query for all  
> > results
> 
> > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > {"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":"true"}'  
> > {  
> > ...  
> > "hits" : {  
> > ...  
> > "hits" : [ {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 0.98479235,  
> > ...  
> > }, {  
> > "\_shard" : 0,  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.1610101,  
> > ...  
> > }, {  
> > "\_shard" : 1,  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.1610101,  
> > ...  
> > } ]  
> > }
> 
> > }
> 
> > It looks like search\_type=dfs\_query\_then\_fetch is being taken into  
> > account in the score calculation (expressed in \_explanation.value),  
> > but the shard-level score is actually being returned for \_score.
> 
> > Note I've been using v0.18.5 for all of these examples (apologies for  
> > not mentioning that earlier). Using an identical set of repro steps,  
> > I see the same issue in v0.17.0, but I don't see the same issue in  
> > v0.16.4. With v0.16.4, I get the following:
> 
> > - Query with "explain":true using the default search\_type and note  
> > \_explanation.value matches \_score for each result.  
> > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > '{"query":{"bool":{"must":[{"text":{"name":"Foo  
> > Bar"}}]}},"explain":true}'  
> > {  
> > ...  
> > "hits" : {  
> > ...  
> > "hits" : [ {  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 0.7271175,  
> > ...  
> > }, {  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.1519148,  
> > ...  
> > }, {  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.04500804,  
> > ...  
> > } ]  
> > }
> 
> > }
> 
> > - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> > note the following:
> > - \_explanation.value matches \_score
> > - \_explanation.value (and \_score) differs from \_explanation.value in  
> > the default search\_type query
> 
> > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > {"must":[{"text":{"name":"Foo Bar"}}]}},"explain":true}'  
> > {  
> > ...  
> > "hits" : {  
> > ...  
> > "hits" : [ {  
> > ...  
> > "\_id" : "1",  
> > "\_score" : 0.98479235, "\_source" : { "name" : "Foo Bar" },  
> > "\_explanation" : {  
> > "value" : 0.98479235,  
> > ...  
> > }, {  
> > ...  
> > "\_id" : "3",  
> > "\_score" : 0.1610101, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.1610101,  
> > ...  
> > }, {  
> > ...  
> > "\_id" : "2",  
> > "\_score" : 0.1610101, "\_source" : { "name" : "Foo" },  
> > "\_explanation" : {  
> > "value" : 0.1610101,  
> > ...  
> > } ]  
> > }
> 
> > }
> 
> > It looks like something changed between v0.16.4 and v0.17.0 that  
> > caused \_score to not be set to \_explanation.value, and it looks like  
> > \_explanation.value is taking the dfs portion of the search into  
> > account. Can I assume the behavior in v0.16.4 is correct? Or was the  
> > scoring behavior intentionally changed in v0.17.0? I'll try to find  
> > the actual code change in the elasticsearch that caused this (I'd  
> > appreciate any pointers you may have since I'm not familiar with the  
> > codebase).
> 
> > Thanks,  
> > Cole
> 
> > On Dec 13, 3:01 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > > If \_explanation.value was still showing shard-level scoring, wouldn't  
> > > the \_explanation.value fields be the same between the second and third  
> > > example I gave (the 2-shard example without search\_type specified vs.  
> > > the 2-shard example with search\_type=dfs\_query\_then\_fetch)? In the  
> > > second example, \_explanation.value is different for hits 2 and 3  
> > > (which is what I was attempting to "fix"). In the third example,  
> > > \_explanation.value is the same for hits 2 and 3, which leads me to  
> > > believe the dfs scoring is being reflected in \_explanation.value.
> 
> > > -cole
> 
> > > On Dec 13, 2:21 pm, Shay Banon [kim...@gmail.com](mailto:kim...@gmail.com) wrote:
> 
> > > > I need to double check, but the explanation part will not take the dfs  
> > > > scoring into account when it shows it (so it will still show shard level  
> > > > scoring), but the \_score will.
> 
> > > > On Wed, Dec 14, 2011 at 12:13 AM, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> > > > 
> > > > > Hello,
> 
> > > > > I'm running into issues with inconsistently scored documents between  
> > > > > different index configurations, and I think may be misunderstanding  
> > > > > some of the basics of how scores are calculated. Repro details are  
> > > > > below, but my basic question is how a hit's \_score relates to its  
> > > > > \_explanation.value (provided when "explain" : true is set in the  
> > > > > query). I understand scores are by default calculated within each  
> > > > > shard, but I thought passing search\_type=dfs\_query\_then\_fetch would  
> > > > > lead to the calculation of globally "correct" scores.
> 
> > > > > Repro steps:
> 
> > > > > [start with empty index, configured with 1 or 2 shards as called out  
> > > > > below]  
> > > > > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > > > > Bar" }'  
> > > > > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" : "Foo  
> > > > > Zip" }'  
> > > > > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" : "Zap  
> > > > > Foo" }'  
> > > > > curl -XPUThttp://localhost:9200/index/mytype/4-d'{ "name" :  
> > > > > "Something Else" }'
> 
> > > > > When the index is configure to use one shard, I get the following  
> > > > > results as expected. Note this is the desired result ("Foo Bar" is  
> > > > > scored highest and "Foo Zip" and "Zap Foo" are tied for second best).
> 
> > > > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d '{"query":  
> > > > > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > > > > {
> 
> ...
> 
> read more »

---

<div class="post-metadata">

**Author:** ![kimchy](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/kimchy/32/44952_2.png) [@kimchy](https://discuss.elastic.co/u/kimchy)\
**Post date:** [December 16, 2011, 5:02pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/7 "2011-12-16T17:02:10Z")

</div>

Heya,

Great work tracking this down!. I did not fully understand your problem  
(next time, its better to have code samples in a gist, and a description in  
the mail, otherwise, its really hard to make sense of it).

The problem happen because you search against the type as well. What  
happens is that the search will be automatically filtered by the type, and  
then it will not match the "provided" query to apply the dfs cals. Opened  
an issue: [Search: When searching against a type with a dfs search type, dfs is ignored · Issue #1546 · elastic/elasticsearch · GitHub](https://github.com/elasticsearch/elasticsearch/issues/1546).

On Fri, Dec 16, 2011 at 2:01 AM, cole [cole.rottweiler@gmail.com](mailto:cole.rottweiler@gmail.com) wrote:

> Commit 882ccf32c826eed14950ba64c76df656ef45c01e caused the change in  
> dfs\_query\_then\_fetch behavior. Specifically, this following change is  
> responsible:
> 
> diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/  
> search/internal/ContextIndexSearcher.java b/modules/elasticsearch/src/  
> main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java  
> index f09683f..9c1149b 100644  
> --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/  
> internal/ContextIndexSearcher.java  
> +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/  
> internal/ContextIndexSearcher.java  
> @@ -131,10 +131,11 @@ public class ContextIndexSearcher extends  
> ExtendedIndexSearcher {  
> }
> 
> ```
> @Override public Weight createNormalizedWeight(Query query)
> 
> ```
> 
> throws IOException {
> 
> - 
> 
> ```
> if (dfSource == null) {
> 
> ```
> 
> - 
> 
> ```
> return super.createNormalizedWeight(query);
> 
> ```
> 
> - 
> 
> ```
> // if its the main query, use we have dfs data, only then do
> 
> ```
> 
> it
> 
> - 
> 
> ```
> if (dfSource != null && (query == searchContext.query() ||
> 
> ```
> 
> query == searchContext.parsedQuery().query())) {
> 
> - 
> 
> ```
> return dfSource.createNormalizedWeight(query);
> }
> 
> ```
> 
> - 
> 
> ```
> return dfSource.createNormalizedWeight(query);
> 
> ```
> 
> - 
> 
> ```
> return super.createNormalizedWeight(query);
> 
> ```
> 
> }
> 
> Shay, can you shed some light on that change (the commit message was  
> "only use dfs data on main query executed")? If I change the code  
> back on the v0.18.5 tag, I get the dfs\_query\_then\_fetch behavior I  
> expect, but I'm assuming the code you added affects more complex query  
> types (parent-child queries by the looks of the unit test added in the  
> same commit). Did you intend for the change to also affect the basic  
> dfs\_query\_then\_fetch behavior?
> 
> Thanks,  
> Cole
> 
> On Dec 15, 12:28 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > Correction: I didn't see version 0.16.5. The behavior of  
> > dfs\_query\_then\_fetch is the same between v0.16.4 and v0.16.5. The  
> > change in behavior is between v0.16.5 and v0.17.0.
> > 
> > -cole
> > 
> > On Dec 15, 11:54 am, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> > 
> > > Hi Shay,
> > 
> > > I've made some progress in debugging the issue I'm seeing with  
> > > dfs\_query\_then\_fetch (the search\_type=dfs\_query\_then\_fetch behavior  
> > > appears to have changed between v0.16.4 and v0.17.0 -- see the full  
> > > details of my investigation below).
> > 
> > > A simpler example than the one I originally gave is the following:
> > 
> > > - Create a fresh index configured to use 2 shards.
> > 
> > > - Add a few simple documents:  
> > > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > > Bar" }'  
> > > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" :  
> > > "Foo" }'  
> > > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" :  
> > > "Foo" }'
> > 
> > > - Query using the default search\_type:  
> > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> > > {  
> > > ...  
> > > "hits" : {  
> > > ...  
> > > "hits" : [ {  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> > > }, {  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> > > }, {  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> > > } ]  
> > > }
> > 
> > > }
> > 
> > > - Query using search\_type=dfs\_query\_then\_fetch (note the results are  
> > > exactly the same as the first query):  
> > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > {"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> > > {  
> > > ...  
> > > "hits" : {  
> > > ...  
> > > "hits" : [ {  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> > > }, {  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> > > }, {  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> > > } ]  
> > > }
> > 
> > > }
> > 
> > > - Query with "explain":true using the default search\_type and note  
> > > \_explanation.value matches \_score for each result.  
> > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}},  
> > > "explain":"true"}'  
> > > {  
> > > ...  
> > > "hits" : {  
> > > ...  
> > > "hits" : [ {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 0.7271175,  
> > > ...  
> > > }, {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.1519148,  
> > > ...  
> > > }, {  
> > > "\_shard" : 1,  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.04500804,  
> > > ...  
> > > } ]  
> > > }
> > 
> > > }
> > 
> > > - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> > > note the following:
> > > - \_explanation.value differ from \_score
> > > - \_explanation.value differs from \_explanation.value in the default  
> > > search\_type query
> > > - \_score matches \_score from the default search\_type query for all  
> > > results
> > 
> > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > {"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":"true"}'  
> > > {  
> > > ...  
> > > "hits" : {  
> > > ...  
> > > "hits" : [ {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 0.98479235,  
> > > ...  
> > > }, {  
> > > "\_shard" : 0,  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.1610101,  
> > > ...  
> > > }, {  
> > > "\_shard" : 1,  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.1610101,  
> > > ...  
> > > } ]  
> > > }
> > 
> > > }
> > 
> > > It looks like search\_type=dfs\_query\_then\_fetch is being taken into  
> > > account in the score calculation (expressed in \_explanation.value),  
> > > but the shard-level score is actually being returned for \_score.
> > 
> > > Note I've been using v0.18.5 for all of these examples (apologies for  
> > > not mentioning that earlier). Using an identical set of repro steps,  
> > > I see the same issue in v0.17.0, but I don't see the same issue in  
> > > v0.16.4. With v0.16.4, I get the following:
> > 
> > > - Query with "explain":true using the default search\_type and note  
> > > \_explanation.value matches \_score for each result.  
> > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > '{"query":{"bool":{"must":[{"text":{"name":"Foo  
> > > Bar"}}]}},"explain":true}'  
> > > {  
> > > ...  
> > > "hits" : {  
> > > ...  
> > > "hits" : [ {  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 0.7271175,  
> > > ...  
> > > }, {  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.1519148,  
> > > ...  
> > > }, {  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.04500804,  
> > > ...  
> > > } ]  
> > > }
> > 
> > > }
> > 
> > > - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> > > note the following:
> > > - \_explanation.value matches \_score
> > > - \_explanation.value (and \_score) differs from \_explanation.value in  
> > > the default search\_type query
> > 
> > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > {"must":[{"text":{"name":"Foo Bar"}}]}},"explain":true}'  
> > > {  
> > > ...  
> > > "hits" : {  
> > > ...  
> > > "hits" : [ {  
> > > ...  
> > > "\_id" : "1",  
> > > "\_score" : 0.98479235, "\_source" : { "name" : "Foo Bar" },  
> > > "\_explanation" : {  
> > > "value" : 0.98479235,  
> > > ...  
> > > }, {  
> > > ...  
> > > "\_id" : "3",  
> > > "\_score" : 0.1610101, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.1610101,  
> > > ...  
> > > }, {  
> > > ...  
> > > "\_id" : "2",  
> > > "\_score" : 0.1610101, "\_source" : { "name" : "Foo" },  
> > > "\_explanation" : {  
> > > "value" : 0.1610101,  
> > > ...  
> > > } ]  
> > > }
> > 
> > > }
> > 
> > > It looks like something changed between v0.16.4 and v0.17.0 that  
> > > caused \_score to not be set to \_explanation.value, and it looks like  
> > > \_explanation.value is taking the dfs portion of the search into  
> > > account. Can I assume the behavior in v0.16.4 is correct? Or was the  
> > > scoring behavior intentionally changed in v0.17.0? I'll try to find  
> > > the actual code change in the elasticsearch that caused this (I'd  
> > > appreciate any pointers you may have since I'm not familiar with the  
> > > codebase).
> > 
> > > Thanks,  
> > > Cole
> > 
> > > On Dec 13, 3:01 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> > 
> > > > If \_explanation.value was still showing shard-level scoring, wouldn't  
> > > > the \_explanation.value fields be the same between the second and  
> > > > third  
> > > > example I gave (the 2-shard example without search\_type specified vs.  
> > > > the 2-shard example with search\_type=dfs\_query\_then\_fetch)? In the  
> > > > second example, \_explanation.value is different for hits 2 and 3  
> > > > (which is what I was attempting to "fix"). In the third example,  
> > > > \_explanation.value is the same for hits 2 and 3, which leads me to  
> > > > believe the dfs scoring is being reflected in \_explanation.value.
> > 
> > > > -cole
> > 
> > > > On Dec 13, 2:21 pm, Shay Banon [kim...@gmail.com](mailto:kim...@gmail.com) wrote:
> > 
> > > > > I need to double check, but the explanation part will not take the  
> > > > > dfs  
> > > > > scoring into account when it shows it (so it will still show shard  
> > > > > level  
> > > > > scoring), but the \_score will.
> > 
> > > > > On Wed, Dec 14, 2011 at 12:13 AM, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com)  
> > > > > wrote:
> > > > > 
> > > > > > Hello,
> > 
> > > > > > I'm running into issues with inconsistently scored documents  
> > > > > > between  
> > > > > > different index configurations, and I think may be  
> > > > > > misunderstanding  
> > > > > > some of the basics of how scores are calculated. Repro details  
> > > > > > are  
> > > > > > below, but my basic question is how a hit's \_score relates to its  
> > > > > > \_explanation.value (provided when "explain" : true is set in the  
> > > > > > query). I understand scores are by default calculated within  
> > > > > > each  
> > > > > > shard, but I thought passing search\_type=dfs\_query\_then\_fetch  
> > > > > > would  
> > > > > > lead to the calculation of globally "correct" scores.
> > 
> > > > > > Repro steps:
> > 
> > > > > > [start with empty index, configured with 1 or 2 shards as called  
> > > > > > out  
> > > > > > below]  
> > > > > > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > > > > > Bar" }'  
> > > > > > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" : "Foo  
> > > > > > Zip" }'  
> > > > > > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" : "Zap  
> > > > > > Foo" }'  
> > > > > > curl -XPUThttp://localhost:9200/index/mytype/4-d'{ "name" :  
> > > > > > "Something Else" }'
> > 
> > > > > > When the index is configure to use one shard, I get the following  
> > > > > > results as expected. Note this is the desired result ("Foo Bar"  
> > > > > > is  
> > > > > > scored highest and "Foo Zip" and "Zap Foo" are tied for second  
> > > > > > best).
> > 
> > > > > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > > > > '{"query":  
> > > > > > {"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":true}'  
> > > > > > {
> > 
> > ...
> > 
> > read more »

---

<div class="post-metadata">

**Author:** ![cole](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@cole](https://discuss.elastic.co/u/cole)\
**Post date:** [December 16, 2011, 7:32pm UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/8 "2011-12-16T19:32:45Z")

</div>

Fantastic. Thanks for the quick fix, Shay. I verified it using my  
basic repro case against a local build off change  
cb4c249a659b0ecee292f45c7f00aefd8ca0411e.

Apologies for the long emails. I realized how unreadable those were  
when I received them myself, and I've resolved to use gist in the  
future. =)

Thanks,  
Cole

On Dec 16, 9:02 am, Shay Banon [kim...@gmail.com](mailto:kim...@gmail.com) wrote:

> Heya,
> 
> Great work tracking this down!. I did not fully understand your problem  
> (next time, its better to have code samples in a gist, and a description in  
> the mail, otherwise, its really hard to make sense of it).
> 
> The problem happen because you search against the type as well. What  
> happens is that the search will be automatically filtered by the type, and  
> then it will not match the "provided" query to apply the dfs cals. Opened  
> an issue:[Search: When searching against a type with a dfs search type, dfs is ignored · Issue #1546 · elastic/elasticsearch · GitHub](https://github.com/elasticsearch/elasticsearch/issues/1546).
> 
> On Fri, Dec 16, 2011 at 2:01 AM, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > Commit 882ccf32c826eed14950ba64c76df656ef45c01e caused the change in  
> > dfs\_query\_then\_fetch behavior. Specifically, this following change is  
> > responsible:
> 
> > diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/  
> > search/internal/ContextIndexSearcher.java b/modules/elasticsearch/src/  
> > main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java  
> > index f09683f..9c1149b 100644  
> > --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/  
> > internal/ContextIndexSearcher.java  
> > +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/  
> > internal/ContextIndexSearcher.java  
> > @@ -131,10 +131,11 @@ public class ContextIndexSearcher extends  
> > ExtendedIndexSearcher {  
> > }
> 
> > ```
> > @Override public Weight createNormalizedWeight(Query query)
> > 
> > ```
> > 
> > throws IOException {
> > 
> > - 
> > 
> > ```
> > if (dfSource == null) {
> > 
> > ```
> > 
> > - 
> > 
> > ```
> > return super.createNormalizedWeight(query);
> > 
> > ```
> > 
> > - 
> > 
> > ```
> > // if its the main query, use we have dfs data, only then do
> > 
> > ```
> > 
> > it
> > 
> > - 
> > 
> > ```
> > if (dfSource != null && (query == searchContext.query() ||
> > 
> > ```
> > 
> > query == searchContext.parsedQuery().query())) {
> > 
> > - 
> > 
> > ```
> > return dfSource.createNormalizedWeight(query);
> > }
> > 
> > ```
> > 
> > - 
> > 
> > ```
> > return dfSource.createNormalizedWeight(query);
> > 
> > ```
> > 
> > - 
> > 
> > ```
> > return super.createNormalizedWeight(query);
> > 
> > ```
> > 
> > }
> 
> > Shay, can you shed some light on that change (the commit message was  
> > "only use dfs data on main query executed")? If I change the code  
> > back on the v0.18.5 tag, I get the dfs\_query\_then\_fetch behavior I  
> > expect, but I'm assuming the code you added affects more complex query  
> > types (parent-child queries by the looks of the unit test added in the  
> > same commit). Did you intend for the change to also affect the basic  
> > dfs\_query\_then\_fetch behavior?
> 
> > Thanks,  
> > Cole
> 
> > On Dec 15, 12:28 pm, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> > 
> > > Correction: I didn't see version 0.16.5. The behavior of  
> > > dfs\_query\_then\_fetch is the same between v0.16.4 and v0.16.5. The  
> > > change in behavior is between v0.16.5 and v0.17.0.
> 
> > > -cole
> 
> > > On Dec 15, 11:54 am, cole [cole.rottwei...@gmail.com](mailto:cole.rottwei...@gmail.com) wrote:
> 
> > > > Hi Shay,
> 
> > > > I've made some progress in debugging the issue I'm seeing with  
> > > > dfs\_query\_then\_fetch (the search\_type=dfs\_query\_then\_fetch behavior  
> > > > appears to have changed between v0.16.4 and v0.17.0 -- see the full  
> > > > details of my investigation below).
> 
> > > > A simpler example than the one I originally gave is the following:
> 
> > > > - Create a fresh index configured to use 2 shards.
> 
> > > > - Add a few simple documents:  
> > > > curl -XPUThttp://localhost:9200/index/mytype/1-d'{ "name" : "Foo  
> > > > Bar" }'  
> > > > curl -XPUThttp://localhost:9200/index/mytype/2-d'{ "name" :  
> > > > "Foo" }'  
> > > > curl -XPUThttp://localhost:9200/index/mytype/3-d'{ "name" :  
> > > > "Foo" }'
> 
> > > > - Query using the default search\_type:  
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > > '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> > > > {  
> > > > ...  
> > > > "hits" : {  
> > > > ...  
> > > > "hits" : [ {  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> > > > } ]  
> > > > }
> 
> > > > }
> 
> > > > - Query using search\_type=dfs\_query\_then\_fetch (note the results are  
> > > > exactly the same as the first query):  
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > > {"must":[{"text":{"name":"Foo Bar"}}]}}}'  
> > > > {  
> > > > ...  
> > > > "hits" : {  
> > > > ...  
> > > > "hits" : [ {  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" }  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" }  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" }  
> > > > } ]  
> > > > }
> 
> > > > }
> 
> > > > - Query with "explain":true using the default search\_type and note  
> > > > \_explanation.value matches \_score for each result.  
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > > '{"query":{"bool":{"must":[{"text":{"name":"Foo Bar"}}]}},  
> > > > "explain":"true"}'  
> > > > {  
> > > > ...  
> > > > "hits" : {  
> > > > ...  
> > > > "hits" : [ {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.7271175,  
> > > > ...  
> > > > }, {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.1519148,  
> > > > ...  
> > > > }, {  
> > > > "\_shard" : 1,  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.04500804,  
> > > > ...  
> > > > } ]  
> > > > }
> 
> > > > }
> 
> > > > - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> > > > note the following:
> > > > - \_explanation.value differ from \_score
> > > > - \_explanation.value differs from \_explanation.value in the default  
> > > > search\_type query
> > > > - \_score matches \_score from the default search\_type query for all  
> > > > results
> 
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > > {"must":[{"text":{"name":"Foo Bar"}}]}}, "explain":"true"}'  
> > > > {  
> > > > ...  
> > > > "hits" : {  
> > > > ...  
> > > > "hits" : [ {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.98479235,  
> > > > ...  
> > > > }, {  
> > > > "\_shard" : 0,  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.1610101,  
> > > > ...  
> > > > }, {  
> > > > "\_shard" : 1,  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.1610101,  
> > > > ...  
> > > > } ]  
> > > > }
> 
> > > > }
> 
> > > > It looks like search\_type=dfs\_query\_then\_fetch is being taken into  
> > > > account in the score calculation (expressed in \_explanation.value),  
> > > > but the shard-level score is actually being returned for \_score.
> 
> > > > Note I've been using v0.18.5 for all of these examples (apologies for  
> > > > not mentioning that earlier). Using an identical set of repro steps,  
> > > > I see the same issue in v0.17.0, but I don't see the same issue in  
> > > > v0.16.4. With v0.16.4, I get the following:
> 
> > > > - Query with "explain":true using the default search\_type and note  
> > > > \_explanation.value matches \_score for each result.  
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?pretty=1' -d  
> > > > '{"query":{"bool":{"must":[{"text":{"name":"Foo  
> > > > Bar"}}]}},"explain":true}'  
> > > > {  
> > > > ...  
> > > > "hits" : {  
> > > > ...  
> > > > "hits" : [ {  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 0.72711754, "\_source" : { "name" : "Foo Bar" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.7271175,  
> > > > ...  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.1519148, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.1519148,  
> > > > ...  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.04500804, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.04500804,  
> > > > ...  
> > > > } ]  
> > > > }
> 
> > > > }
> 
> > > > - Query with "explain":true using search\_type=def\_query\_then\_fetch and  
> > > > note the following:
> > > > - \_explanation.value matches \_score
> > > > - \_explanation.value (and \_score) differs from \_explanation.value in  
> > > > the default search\_type query
> 
> > > > curl -XGET 'localhost:9200/index/mytype/\_search?  
> > > > pretty=1&search\_type=dfs\_query\_then\_fetch' -d '{"query":{"bool":  
> > > > {"must":[{"text":{"name":"Foo Bar"}}]}},"explain":true}'  
> > > > {  
> > > > ...  
> > > > "hits" : {  
> > > > ...  
> > > > "hits" : [ {  
> > > > ...  
> > > > "\_id" : "1",  
> > > > "\_score" : 0.98479235, "\_source" : { "name" : "Foo Bar" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.98479235,  
> > > > ...  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "3",  
> > > > "\_score" : 0.1610101, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.1610101,  
> > > > ...  
> > > > }, {  
> > > > ...  
> > > > "\_id" : "2",  
> > > > "\_score" : 0.1610101, "\_source" : { "name" : "Foo" },  
> > > > "\_explanation" : {  
> > > > "value" : 0.1610101,  
> > > > ...  
> > > > } ]  
> > > > }
> 
> > > > }
> 
> > > > It looks like something changed
> 
> ...
> 
> read more »

---

<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:** [July 6, 2017, 3:45am UTC](https://discuss.elastic.co/t/inconsistent-document-scores-using-search-type-dfs-query-then-fetch-how-do-the--score-and--explanation-value-fields-relate/6151/9 "2017-07-06T03:45:07Z")

</div>


