Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter on empty string using ElasticSearch/Nest

This may be a silly question, but how do I filter on an empty string in ElasticSearch using Nest. Specifically, how do I recreate the following result:

curl http://localhost:9200/test/event/_search
{
    "filter" : { "term" : { "target" : "" }}
}

I've tried:

(f => f
    .Term("target", "")
);

which according to ElasticSearch and Nest filtering does not work is treated like a conditionless query and returns everything, while adding a .Strict() throws a DslException:

(f => f
    .Strict().Term("target", "")
);

I've also tried .Missing() and .Exists() to no avail.

The relevant section of my _mapping for reference:

{
    "event": {
        "dynamic": "false",
        "properties": {
            target": {
                "type": "string",
                "index": "not_analyzed",
                "store": true,
                "omit_norms": true,
                "index_options": "docs"
            }
        }
    }
}

Any pointers would be greatly appreciated.

like image 403
user1664295 Avatar asked Dec 04 '13 01:12

user1664295


2 Answers

As the documentation on NEST and writing queries mentions you can toggle Strict() mode to trigger exceptions if a part of your query turns out to be conditionless but if thats what you really wanted then you were stuck as you've found out.

I just committed a .Verbatim() construct which works exactly like .Strict() but instead of throwing an exception it will take the query as is and render it as specified.

(f => f
    .Verbatim()
    .Term("target", "")
);

Should thus disable the conditionless query rewrite and insert the query literally as specified.

This will make it in the next version of NEST (so after the current version of 0.12.0.0)

like image 177
Martijn Laarman Avatar answered Nov 19 '22 22:11

Martijn Laarman


I will just remark that you have to use Verbatim() on every query, not just once on the top.

var searchResults = this.Client.Search<Project>(s => s
    .Query(q => q
        //.Verbatim() // no, here won't work
        .Bool(b => b
            .Should(
                bs => bs.Match(p => p.Query("hello").Field("name").Verbatim()),
                bs => bs.Match(p => p.Query("world").Field("name").Verbatim())
            )
        )
    )
);
like image 20
andrew.fox Avatar answered Nov 20 '22 00:11

andrew.fox