# "Relaxing" query

**URL:** <https://discuss.elastic.co/t/relaxing-query/126044>\
**Category:** Elasticsearch\
**Created:** [March 29, 2018, 8:20am UTC](https://discuss.elastic.co/t/relaxing-query/126044 "2018-03-29T08:20:01Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![aclowkey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aclowkey/32/51020_2.png) [@aclowkey](https://discuss.elastic.co/u/aclowkey)\
**Post date:** [March 29, 2018, 8:20am UTC](https://discuss.elastic.co/t/relaxing-query/126044/1 "2018-03-29T08:20:01Z")

</div>

Is there a way to "relax" a query when there are no matches?

For example, if a user searches "red shirts" and the operator is "AND" and there are no results, the operator would change to "OR"

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [March 29, 2018, 12:18pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/2 "2018-03-29T12:18:28Z")

</div>

You can use a bool query with 2 should clauses.

The And one with a boost  
The Or one without any boost

So you will get both but elements which match AND will be on top.

A full example here:

> <https://gist.github.com/dadoonet/5179ee72ecbf08f12f53d4bda1b76bab>

---

<div class="post-metadata">

**Author:** ![aclowkey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aclowkey/32/51020_2.png) [@aclowkey](https://discuss.elastic.co/u/aclowkey)\
**Post date:** [March 29, 2018, 12:31pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/3 "2018-03-29T12:31:43Z")

</div>

Thanks, But we have the TF-IDF disabled for custom relevancy scoring, so it's a different use case

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [March 29, 2018, 2:05pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/4 "2018-03-29T14:05:42Z")

</div>

Even with no score I think what I said is still valid. Did you try?

---

<div class="post-metadata">

**Author:** ![aclowkey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aclowkey/32/51020_2.png) [@aclowkey](https://discuss.elastic.co/u/aclowkey)\
**Post date:** [March 29, 2018, 2:46pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/5 "2018-03-29T14:46:24Z")

</div>

I think I get your idea and I haven't tried it because I think it won't help because it relies on boosting the AND matches and, sort of, downranking the OR matches

In such case, it will be equivalent to an OR query. So in my example, if there ARE "red shirts" I would also get results for products which don't match both terms.

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [March 29, 2018, 10:06pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/6 "2018-03-29T22:06:10Z")

</div>

Yes. But they will be less important.

Otherwise you can do something like this I think:

```
bool
  Should 
    Match (and)
    Bool
      Must not
         Match (and)
      Must 
         Match (or)
```

---

<div class="post-metadata">

**Author:** ![Mark\_Harwood](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/mark_harwood/32/10538_2.png) [@Mark\_Harwood](https://discuss.elastic.co/u/Mark_Harwood)\
**Post date:** [March 30, 2018, 8:14am UTC](https://discuss.elastic.co/t/relaxing-query/126044/7 "2018-03-30T08:14:34Z")

</div>

We don’t know there are no results until all matches are returned to the coordinating node so this is not something that can be figured out on individual data nodes in a distributed system.  
I know of search consultancies who put this sort of relaxation logic in their app’s client code for elasticsearch. The “tight” query is preferable because, yes, a “sloppy OR tight” query should still rank best hits the same way but will make a mess of any aggregations used to filter by things like department

---

<div class="post-metadata">

**Author:** ![aclowkey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aclowkey/32/51020_2.png) [@aclowkey](https://discuss.elastic.co/u/aclowkey)\
**Post date:** [March 30, 2018, 12:55pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/8 "2018-03-30T12:55:19Z")

</div>

They would less important according to TF-IDF, but it's disabled..

> [@dadoonet](#):
>
> Yes. But they will be less important.
> 
> Otherwise you can do something like this I think:
> 
> ```
> bool
> Should 
> Match (and)
> Bool
> Must not
> Match (and)
> Must 
> Match (or)
> 
> ```

---

<div class="post-metadata">

**Author:** ![aclowkey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aclowkey/32/51020_2.png) [@aclowkey](https://discuss.elastic.co/u/aclowkey)\
**Post date:** [March 30, 2018, 12:57pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/9 "2018-03-30T12:57:34Z")

</div>

So I think I will go with implementing it on the application side. Thanks

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [March 30, 2018, 1:17pm UTC](https://discuss.elastic.co/t/relaxing-query/126044/10 "2018-03-30T13:17:59Z")

</div>

When TFIDF is disabled the score is 1 I think.

So you will have documents with a score of 3 (match on AND but boosted + match on OR) and documents with a score of 1 (match on OR).

I think. Did you test it?

---

<div class="post-metadata">

**Author:** ![aclowkey](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aclowkey/32/51020_2.png) [@aclowkey](https://discuss.elastic.co/u/aclowkey)\
**Post date:** [April 4, 2018, 9:31am UTC](https://discuss.elastic.co/t/relaxing-query/126044/11 "2018-04-04T09:31:52Z")

</div>

It works fine when TF-IDF is enabled, however we have custom scoring so TF-IDF isn't considered at all. My function\_score query replaces the score..

---

<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:** [May 2, 2018, 9:31am UTC](https://discuss.elastic.co/t/relaxing-query/126044/12 "2018-05-02T09:31:56Z")

</div>

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