2016-03-30 2 views
0

При попытке сортировать числовые поля datetime (long), я всегда получаю исключение FormatException.Lucene - Sorting Date as NumericField

When converting a string to DateTime, parse the string to take the date before putting each variable into the DateTime object.

Добавление числового поля: сортировка

doc.Add(new NumericField("creationDate", Field.Store.YES, true) 
    .SetLongValue(DateTime.UtcNow.Ticks); 

Добавить:

// boolean query  
var sortField = new SortField("creationDate", SortField.LONG, true); 
var inverseSort = new Sort(sortField); 
var results = searcher.Search(query, null, 100, inverseSort); // exception thrown here 

Проверка индекса, я могу проверить, что поле 'CreationDate' хранит "длинные" значения. Что может вызвать это исключение?

EDIT:

Запрос

var query = new BooleanQuery(); 
foreach (var termQuery in incomingProps.Select(p => new TermQuery(new Term(kvp.Key, kvp.Value.ToLowerInvariant())) 
{ 
    query.Add(new BooleanClause(termQuery , Occur.Must)); 
} 

return query; 

Версия: 3.0.3 Lucene.Net

UPDATE:

Эта проблема происходит снова, теперь со значениями INT. Я загрузил исходный код Lucene.Net и отладил проблему.

Так что это где-то в FieldCache при попытке проанализировать значение «` \ b \ 0 \ 0 \ 0 »на Integer, что кажется немного странным.

FieldCacheException

Я добавляю эти значения числовых полей:

doc.Add(new NumericField(VersionNum, int.MaxValue, Field.Store.YES, 
true).SetIntValue(VersionValue)); 

я получаю исключение, когда я должен получить по крайней мере один удар обратно. После проверки индекса я вижу, что термин поле является следующим:

Version Term

И текстовое поле:

enter image description here

EDIT:

Я жёстко int и добавлено несколько сегментов:

doc.Add(new Field(VersionNum, NumericUtils.IntToPrefixCoded(1), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); 

Что привело на хранение поле версии, как: enter image description here

И еще, когда я пытаюсь разобраться, я получаю ошибку синтаксического анализа:

var sortVersion = new SortField(VersionNum, SortField.INT, true); 

Для каждого исключения, Lucene пытается разобрать "\ b \ 0 \ 0 \ 0 ". Глядя на префикс, закодированный в виде строки, 1 переведет на «\ b \ 0 \ 0 \ 0 \ 1», я предполагаю?

Возможно ли, что Lucene оставляет мусор в FieldCache?

+0

Вы можете показать, как создается «запрос»? – AndyPook

+0

@ AndyPook Только что отредактировал вопрос и добавил «запрос». Он отлично работает, если я сортирую DOC. –

+0

Поле даты не включено в запрос, оно используется только для сортировки. Допустим, что я запрашиваю только пользовательский идентификатор поля, который предоставляется для возврата набора результатов. –

ответ

1

Вот блок-тест, который пытается захватить то, что вы просите. Тест проходит. Можете ли вы объяснить, какая разница с вашим кодом?(публикация полного теста на провал поможет нам понять, что вы делаете :-))

using System; 
using System.Linq; 
using System.Collections.Generic; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

using Lucene.Net.Search; 
using Lucene.Net.Index; 
using Lucene.Net.Analysis.Standard; 
using Lucene.Net.QueryParsers; 
using Lucene.Net.Documents; 
using Lucene.Net.Store; 

namespace SO_answers 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestShopping() 
     { 
      var item = new Dictionary<string, string> 
      { 
       {"field1", "value1" }, 
       {"field2", "value2" }, 
       {"field3", "value3" } 
      }; 

      var writer = CreateIndex(); 
      Add(writer, item); 
      writer.Flush(true, true, true); 

      var searcher = new IndexSearcher(writer.GetReader()); 
      var result = Search(searcher, item); 

      Assert.AreEqual(1, result.Count); 

      writer.Dispose(); 
     } 

     private List<string> Search(IndexSearcher searcher, Dictionary<string, string> values) 
     { 
      var query = new BooleanQuery(); 
      foreach (var termQuery in values.Select(kvp => new TermQuery(new Term(kvp.Key, kvp.Value.ToLowerInvariant())))) 
       query.Add(new BooleanClause(termQuery, Occur.MUST)); 

      return Search(searcher, query); 
     } 

     private List<string> Search(IndexSearcher searcher, Query query) 
     { 
      var sortField = new SortField("creationDate", SortField.LONG, true); 
      var inverseSort = new Sort(sortField); 
      var results = searcher.Search(query, null, 100, inverseSort); // exception thrown here 


      var result = new List<string>(); 
      var matches = results.ScoreDocs; 
      foreach (var item in matches) 
      { 
       var id = item.Doc; 
       var doc = searcher.Doc(id); 
       result.Add(doc.GetField("creationDate").StringValue); 
      } 
      return result; 
     } 

     IndexWriter CreateIndex() 
     { 
      var directory = new RAMDirectory(); 

      var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30); 
      var writer = new IndexWriter(directory, analyzer, new IndexWriter.MaxFieldLength(1000)); 

      return writer; 
     } 
     void Add(IndexWriter writer, IDictionary<string, string> values) 
     { 
      var document = new Document(); 
      foreach (var kvp in values) 
       document.Add(new Field(kvp.Key, kvp.Value.ToLowerInvariant(), Field.Store.YES, Field.Index.ANALYZED)); 
      document.Add(new NumericField("creationDate", Field.Store.YES, true).SetLongValue(DateTime.UtcNow.Ticks)); 

      writer.AddDocument(document); 
     } 
    } 
} 
+0

Спасибо за ответ, вы всегда были большой помощью. Тем не менее, в этом случае у меня был «забытый» документ среди тысяч с неправильным значением даты. Я отмечу ваш ответ как принятый. спасибо –

+0

Aloha andy, я не отмечен вашим ответом, как принято. Проблема случайная, и я понятия не имею, что происходит. Однако у меня есть некоторые новые результаты, которые могут привести к первопричине. –

+0

Вы обнаружили проблему? – AndyPook