使用Lucene.Net在两个日期之间搜索

时间:2012-03-22 03:31:47

标签: date lucene range lucene.net

在我的Lucene.Net索引中,我有包含startDate字段和endDate字段的文档。两个字段都以yyyyMMdd格式存储日期。如果今天的日期介于这两个日期之间,我如何构建一个将返回命中的查询?

  

startDateFieldValue< myTargetDate< endDateFieldValue

例如,如果myTargetDate是17760604,我想要获取一个startDate字段值为10660101且endDate字段值为19990101的文档。

场景是我有一个Lucene数据库,其中包含代表特定建筑工地的Lucene文档。每个站点都有一个StartConstruction日期和一个EndConstruction日期。我的用户将输入特定日期,我想查找该日期当前正在建设的所有房产。

注意:我正在使用Lucene.Net 1.9,这是一个更老的版本,我的公司还无法升级。

3 个答案:

答案 0 :(得分:6)

您可以使用范围查询执行此操作。具体来说,您可以使用NumericRangeQuery执行此操作。为此,首先使用NumericField索引日期并将其添加到文档中,如:

var df = new NumericField(Fields.AmendedDate);
df.SetIntValue(int.Parse(itemToIndex.startDate.ToString("yyyyMMdd")));
doc.Add(df);

通过在多个文档see the documentation中重复使用NumericField,可以使索引更快一些。随着您的日期都很好地编入索引,您现在可以搜索它了。为此,我们使用NumericRangeQuery:

var q = NumericRangeQuery.NewIntRange(  Fields.AmendedDate,
                                        int.Parse(SearchFrom.ToString("yyyyMMdd")),
                                        int.Parse(SearchTo.ToString("yyyyMMdd")),
                                        true, true);

此查询可用于搜索或连接到现有查询,如:

masterQuery.Add(q, BooleanClause.Occur.MUST);

由于数字字段的索引性质,以这种方式拆分搜索比使用文本术语搜索要快得多。此外,您的分辨率(在本例中为日级)可以更改为更好地分布您的数据(即,如果您需要小时,分钟或秒,然后将它们添加到从最重要到最不重要的字符串)。最后一点是,通过使用查询,您可以忽略搜索的过滤步骤(这是普通查询,而不是过滤器)。

答案 1 :(得分:1)

我不确定我是否正确地表达了我的问题。我想知道特定项目在开始日期和结束日期之间是否有效。 StartDate存储在一个Lucene字段中,EndDate存储在另一个Lucene字段中。

以下是我使用的搜索代码段:

var searchableDate = DateTools.DateToString(dateToSearchFor, DateTools.Resolution.DAY);

var lowerRange = new RangeQuery(null, new Term("StartDate", searchableDate), true);
var upperRange = new RangeQuery(new Term("EndDate", searchableDate), null, true);

var activeTodayFilter = new BooleanQuery();
activeTodayFilter.Add(new BooleanClause(lowerRange, BooleanClause.Occur.MUST));
activeTodayFilter.Add(new BooleanClause(upperRange, BooleanClause.Occur.MUST));
return activeTodayFilter;

我在一个旧的Lucene论坛/新闻组中找到了解决方案,但我担心我不记得这个链接。

如果有更简单/更好的方式来编写上述查询,请告诉我。

答案 2 :(得分:0)

您必须使用RangeQuery

RangeQuery rq = new RangeQuery(new Term("date", "10660101"),new Term("date", "19990101") ,true);

在最新版本中,您可以使用NumericFields / NumericRangeQuery来获得更好的性能。