2015-08-06 5 views
2

У меня есть DateTime? поле, я хочу возвращать элементы, если это поле в будущем, или если его NULL.ElasticSearch NEST Проверка нулевого значения

Проверка NULL является проблемой, ES не хранит нулевые значения, поэтому я не могу ее проверить.

Не существует способа проверить отсутствие существования в .Query?

Я знаю, что могу .Filter(), чтобы заставить ES возвращать элементы, которые не имеют определенного поля, но мне нужно проверить NULL в .Query(), который не работает.

Что у меня есть:

var results = client.Search<ElasticResult>(s => s 
    .Filter(f => f.Missing(ff=>ff.EndTimeUTC) || f.Exists(ff=>ff.EndTimeUTC))   
    .Query(q => q 
    .Term(p => p.ShortDescription, "somevalue") 
    && (q.Range(p => p.OnField(f => f.EndTimeUTC).GreaterOrEquals(DateTime.UtcNow)) || 
     q.Term(t => t.EndTimeUTC, null)) // THIS IS HAVING NO EFFECT 
)); 

Я не уверен, что

.Filter(f => f.Missing("endTimeUTC") || f.Exists("endTimeUTC")) 

ли на самом деле делает никакой разницы, необходимые документы возвращаются в SHORTDESCRIPTION запроса, они просто не «т есть поле endTimeUTC

ответ

2

я думаю, ваш

.Filter(f => f.Missing("endTimeUTC") || f.Exists("endTimeUTC")) 

не имеет смысла, поскольку он фильтрует missing || exists, поэтому он ничего не фильтрует.

Если необходимо выполнить поиск по диапазону и и то же время показывают документы без такого поля, это то, что вам нужно

POST so/t4/ 
{"time": "1900-01-01"} 
POST so/t4/ 
{"time": "2100-01-01"} 
POST so/t4 
{} 

GET so/t4/_search 
{ 
    "query": { 
    "filtered": { 
     "query": { 
     "match_all": {} 
     }, 
     "filter": { 
     "bool": { 
      "should": [ 
      { 
       "range": { 
       "time": { 
        "gte": "now" 
       } 
       } 
      }, 
      { 
       "missing": { 
       "field": "time" 
       } 
      } 
      ] 
     } 
     } 
    } 
    } 
} 

результаты:

{ 
    "took": 2, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 2, 
     "max_score": 1, 
     "hits": [ 
     { 
      "_index": "so", 
      "_type": "t4", 
      "_id": "AU8C4hcnDeuEUel6ntPr", 
      "_score": 1, 
      "_source": { 
       "time": "2100-01-01" 
      } 
     }, 
     { 
      "_index": "so", 
      "_type": "t4", 
      "_id": "AU8C4hr5DeuEUel6ntPs", 
      "_score": 1, 
      "_source": {} 
     } 
     ] 
    } 
} 

should логика делает буквально «данные должен находиться в диапазоне или его должно отсутствовать »

+0

Спасибо! Я не думаю, что мне когда-либо удавалось это сделать самостоятельно. – user3378086

+0

По состоянию на 6.1 отсутствующий запрос был удален. Заменено на! N.Exists https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html#_literal_missing_literal_query – w00ngy

1

Вот синтаксис NEST, в результате которого я оказался

var results = client 
    .Search<ElasticResult>(s => s 
    .Query(q => q 
     .Filtered(filtered => filtered 
      .Query(t=>t.Term(p => p.ShortDescription, "somevalue")) 
      .Filter(ff => ff. 
       Bool(b=> b 
        .Should(n=>n 
         .Range(p => p.OnField(f => f.EndTimeUTC).GreaterOrEquals(DateTime.UtcNow)) 
         || 
         n.Missing(m=>m.EndTimeUTC) 
         ) 
        ) 
       ) 
      ) 
     ) 
    ); 
1

В то же время я также нашел другое, менее элегантное решение. Скажите ES, чтобы обеспечить значение по умолчанию для поля, когда его нуль:

var client = new ElasticClient(settings); 
client.Map<ElasticLotResult>(m=>m 
    .Properties(props => props 
    .Date(s => s 
    .Name(p => p.EndTimeUTC) 
    .NullValue(DateTime.MinValue) 
    )) 
); 

затем запрос и проверить, что нулевое значение по умолчанию:

.Query(q => q 
    .Term(p => p.ShortDescription, "somevalue") 
    && (q.Range(p => p.OnField(f => f.EndTimeUTC).GreaterOrEquals(DateTime.UtcNow)) || 
    q.Term(t => t.EndTimeUTC, DateTime.MinValue)) 
Смежные вопросы