3

All would like to use the filtered query where results should contain data from the "query_string" and also from the "term - filter" applied.

GET blog/_search
{
    "query": {
        "filtered": {
            "query": {
                "query_string": {
                    "fields": [ "description" ],
                    "query": "a"                 // or just ""
                }
            },
            "filter": {
                "terms": {
                    "topic_id": [
                        10
                    ]
                }
            }
        }
    }
}

The expected result is:

  1. all blog records having letter "a" or "" in it with topic_id is 10.
  2. also rest of the records where topic_id is 10 even if the description is blank/empty.

So final result should be - the matching records with higher score and should come at the top, then the records just matching the "topic_id" from the filter.

5
  • When searched with "a", I only get data which contains letter "a" in the description, but I need the data with empty("") description with topic_id 10 too. Also when searched with blank(""), not getting any data. But I expect data with empty description with topic_id 10. Commented Jun 14, 2016 at 10:10
  • The query I am trying is mentioned in the question. Commented Jun 14, 2016 at 10:11
  • this maybe helpful Commented Jun 14, 2016 at 15:39
  • @keety, the link that you gave would not help much as I want both the matches as per the query added as well the empty search but with the filter of topic_id value. The condition 1 that I have mentioned in the question. Commented Jun 14, 2016 at 16:30
  • @KunalDethe check my answer. I thinks that is what you are looking for. Hope it helps Commented Jun 17, 2016 at 8:18

3 Answers 3

2
+50

One way to achieve this is use muti_fields mapping for description field. One of the fields in multi-field should be non-analyzed. Once the data has been reindexed you can use a simple bool query to achieve what you want :

Example

Create Index:

put test
{
    "mappings": {
        "data" : {
            "properties": {
                "description" : {
                    "type": "string",
                     "fields": {
                        "raw" : {"type": "string","index": "not_analyzed"}
                     }
                }
            }   
        }
    }
}

Index Data:

put test/data/1 
{
    "description" : "a",
    "test_id" : 10
}
put test/data/2
{
    "description" : "",
    "test_id" : 10
}

put test/data/3
{
    "description" : "hello",
    "test_id" : 10
}


put test/data/4
{
    "description": "a",
    "test_id" : 20
}

Query:

post test/data/_search
{
   "query": {
      "filtered": {
         "query": {
            "bool": {
               "disable_coord": "true",
               "should": [
                  {
                     "query_string": {
                        "fields": [
                           "description"
                        ],
                        "query": "a"
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "term": {
                              "description.raw": ""
                           }
                        },
                        "boost": 0.2
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "exists": {
                              "field": "description"
                           }
                        },
                        "boost": 0.1
                     }
                  }
               ]
            }
         },
         "filter": {
            "terms": {
               "test_id": [
                  10
               ]
            }
         }
      }
   }
}

Results :

 "hits": [
         {
            "_index": "test",
            "_type": "data",
            "_id": "1",
            "_score": 0.5113713,
            "_source": {
               "description": "a",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "2",
            "_score": 0.29277003,
            "_source": {
               "description": "",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "3",
            "_score": 0.097590014,
            "_source": {
               "description": "hello",
               "test_id": 10
            }
         }
      ]

Query Empty string:

{
   "query": {
      "filtered": {
         "query": {
            "bool": {
               "disable_coord": "true",
               "should": [
                  {
                     "query_string": {
                        "fields": [
                           "description"
                        ],
                        "query": ""
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "term": {
                              "description.raw": ""
                           }
                        },
                        "boost": 0.2
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "exists": {
                              "field": "description"
                           }
                        },
                        "boost": 0.1
                     }
                  }
               ]
            }
         },
         "filter": {
            "terms": {
               "test_id": [
                  10
               ]
            }
         }
      }
   }
} 

Result :

  "hits": [
         {
            "_index": "test",
            "_type": "data",
            "_id": "2",
            "_score": 1.3416407,
            "_source": {
               "description": "",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "1",
            "_score": 0.44721356,
            "_source": {
               "description": "a",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "3",
            "_score": 0.44721356,
            "_source": {
              "description": "hello",
               "test_id": 10
            }
         }
      ]
Sign up to request clarification or add additional context in comments.

8 Comments

Let me try it out.
@KunalDethe curious did the above not work as expected ?
the result that I am getting when search text is empty (""), then only the data with empty description is being returned. But I also want the non-empty to be returned but later in the result. Empty description should take priority over the non-empty.
just to calrify if you are search for "a" you would like "a" results followed by empty string followed by rest of the documents with non-empty and non-"a" . Similary if you search for empty you like empty followed by non empty in the results, is that accurate ?
Yes, need exactly the same.
|
2

Have you considered using wildcard query? Check this query it will work fine for you.

all blog records having letter "a" in it with topic_id is 10.

{
  "filter": {
    "and": [
      {
        "in": {
          "topic_id": [
            "10"
          ]
        }
      },
      {
        "query": {
          "filtered": {
            "filter": {
              "bool": {
                "should": [
                  {
                    "query": {
                      "wildcard": {
                        "description": {
                          "value": "*a*"
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ]
  }
}

Also rest of the records where topic_id is 10 even if the description is blank/empty. This will return all the other records that doesn't match the wildcard.

{
  "filter": {
    "and": [
      {
        "in": {
          "topic_id": [
            "10"
          ]
        }
      },
      {
        "not": {
          "query": {
            "filtered": {
              "filter": {
                "bool": {
                  "should": [
                    {
                      "query": {
                        "wildcard": {
                          "description": {
                            "value": "*a*"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    ]
  }
}

To find only the empty " " description fields with topic_id 10. try this,

{
  "filter": {
    "and": [
      {
        "in": {
          "topic_id": [
            "10"
          ]
        }
      },
      {
        "query": {
          "filtered": {
            "filter": {
              "script": {
                "script": "_source.description.length() == 0"
              }
            }
          }
        }
      }
    ]
  }
}

Comments

2

For ES 2.x

Using a bool query should do the trick.

Here's the query I will use:

GET blog/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "query_string": {
            "fields": [ "description" ],
              "query": "a"
          }
        }
      ],
      "must": [
        {
          "terms": {
            "topic_id": [
              10
            ]
          }
        }
      ]
    }
  }
}

Here, the should clause of the bool query will tell Elassticsearch that document matching the query_string should be returned. In the query_string consider using wildcards if you want to match any document containing a. For example "query_string": { "query": "*a*" }

The must clause in the other hand will tell that, for considering the document a valid match, it must contain 10 in the topic_id field. Wether the should clause could or could not match.

Bool filter

I hope this could help you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.