Solr使用日期字段类型
Solr 日期格式
Solr 的日期字段(DatePointField,DateRangeField 和已过时的 TrieDateField)代表“datas”,如时间精确到毫秒的点。使用的格式是XML Schema规范中 dateTime 的规范化表示形式的限制形式,这是 ISO-8601 的一个受限子集。对于那些熟悉 Java 8 的人来说,Solr 使用 DateTimeFormatter.ISO_INSTANT 进行格式化,并使用 “leniency” 进行解析。
如以下示例:
YYYY-MM-DDThh:mm:ssZ
其中:
- YYYY 是表示年份。
- MM 是表示月份。
- DD 是表示月份的某一天。
- hh 是表示一天24小时的时间。
- mm 是表示分钟。
- ss 是表示秒。
- Z 是一个字面的“Z”字符,表示该日期的字符串表示形式是 UTC。
请注意,不能指定时区。日期的字符串表示形式始终以协调世界时 (UTC) 表示。这是一个示例值:
1972-05-20T17:33:18Z
如果您愿意,您可以选择包含小数的秒数,但任何超出毫秒的精度都将被忽略。下面是 sub-seconds 的示例值:
- 1972-05-20T17:33:18.772Z
- 1972-05-20T17:33:18.77Z
- 1972-05-20T17:33:18.7Z
必须有一个领先的 "-" 符号在0000年前的日期,并且在9999年之后,Solr将会以一个领先的“+”来格式化日期。年0000被认为是公元前1年;没有公元 0 年或公元前 0 年的表达方法。
可能需要查询转义:
如您所见,日期格式包括分隔小时、分钟和秒的冒号字符。因为冒号是 Solr 最常见的查询解析器的特殊字符,所以有时需要转义,具体取决于您正在尝试执行的操作。
这通常是一个无效查询:
datefield: 1972-05-20T17:33:18.772Z
以下这些是有效的查询:
- datefield: 1972-05-20T17 \:33 \: 18.772Z
- datefield: "1972-05-20T17:33:18.772Z"
- datefield: [1972-05-20T17:33:18.772Z TO *]
日期范围格式
Solr 的 DateRangeField 支持上面描述的时间段语法中的相同点(具有下面描述的日期数学)以及更多的表达日期范围。一类示例是截断的日期,它表示整个日期跨度到所指示的精度。另一个类使用范围语法([ TO ])。下面是一些示例:
- 2000-11:2000年11月的整个月
- 2000-11T13:同样,但在一天中的一个小时(1300至1400前,即下午1点至2点)。
- -0009:公元前10年,年份中的 0 是公元 0,也被认为是公元前1年。
- [2000-11-01 TO 2014-12-01]:指定的日期范围在一天的分辨率。
- [2014 TO 2014-12-01]:从 2014 年开始到 12 月的第一天结束。
- [* TO 2014-12-01]:从最早的可代表时间到2014年12月12日的一天结束。
限制:范围语法不支持嵌入日期数学。如果您指定了 DatePointField 支持的日期实例,并将日期数学截断,比如 NOW/DAY,那么您仍然可以得到当天的第一个毫秒,而不是整天的范围。独占范围(使用{&})在查询中工作,但不适用于索引范围。
日期数学
Solr 的日期字段类型也支持日期数学表达式,这使得相对于固定时刻的时间创建变得容易,包括使用“NOW”的特殊值来表示的当前时间。
日期数学表达式
日期数学表达式包括在指定的单位中添加一定量的时间,或者以指定单位四舍五入当前时间。表达式可以链接并从左向右进行评估。
例如:以下代表了两个月后的时间点:
NOW+2MONTHS
这是一天前:
NOW-1DAY
斜线用于表示舍入。这代表当前小时的开始:
NOW/HOUR
下面的例子计算(精确到毫秒)时间为六个月和三天后的时间点,然后将该时间点回溯到当天的开始时间:
NOW+6MONTHS+3DAYS/DAY
请注意,虽然日期数学是相对于 NOW 是最常用的,但它也可以应用于任何固定时间点:
1972-05-20T17:33:18.772Z+6MONTHS+3DAYS/DAY
影响日期数学的请求参数
NOW
该 NOW 参数由 Solr 在内部使用,以确保在分布式请求中的多个节点上分析一致的日期数学表达式。但是可以指定 Solr 使用任意时刻(过去或将来)的任意时刻覆盖“ NOW” 的特殊值会影响日期数学表达式的所有情况。
它必须被指定为自纪元以来的(长值)毫秒。
示例:
q=solr&fq=start_date:[* TO NOW]&NOW=1384387200000
TZ
默认情况下,所有日期数学表达式都是相对于 UTC TimeZone 计算的,但是 TZ 可以指定该参数来覆盖此行为,方法是强制所有基于日期的加法和舍入相对于指定的时区。
例如,下面的请求将使用范围面来面向当前月份,“每天”相对 UTC:
http://localhost:8983/solr/my_collection/select?q=*:*&facet.range=my_date_field&facet=true&facet.range.start=NOW/MONTH&facet.range.end=NOW/MONTH%2B1MONTH&facet.range.gap=%2B1DAY
<int name="2013-11-01T00:00:00Z">0</int>
<int name="2013-11-02T00:00:00Z">0</int>
<int name="2013-11-03T00:00:00Z">0</int>
<int name="2013-11-04T00:00:00Z">0</int>
<int name="2013-11-05T00:00:00Z">0</int>
<int name="2013-11-06T00:00:00Z">0</int>
<int name="2013-11-07T00:00:00Z">0</int>
...
在本例中,“days” 将根据指定的时区进行计算 - 包括任何适用的夏令时间调整:
http://localhost:8983/solr/my_collection/select?q=*:*&facet.range=my_date_field&facet=true&facet.range.start=NOW/MONTH&facet.range.end=NOW/MONTH%2B1MONTH&facet.range.gap=%2B1DAY&TZ=America/Los_Angeles
<int name="2013-11-01T07:00:00Z">0</int>
<int name="2013-11-02T07:00:00Z">0</int>
<int name="2013-11-03T07:00:00Z">0</int>
<int name="2013-11-04T08:00:00Z">0</int>
<int name="2013-11-05T08:00:00Z">0</int>
<int name="2013-11-06T08:00:00Z">0</int>
<int name="2013-11-07T08:00:00Z">0</int>
...
更多 DateRangeField 详细信息
DateRangeField 几乎是 DatePointField 所用地方的替代品。唯一的区别是,Solr 的 XML 或 SolrJ 响应格式将存储的数据作为一个字符串而不是一个日期。该字段的基础索引数据会稍大一些。与时间单位对齐的查询应该比 TrieDateField 快,尤其是在 UTC 的情况下。
DateRangeField,顾名思义,其主要观点是允许索引日期范围。要做到这一点,只需提供上面显示的格式的字符串。它还支持在索引数据和查询范围之间指定3个不同的关系谓词:
- Intersects (默认)
- Contains
- Within
你可以通过查询使用 oplocal-params 参数来指定谓词,如下所示:
fq={!field f=dateRange op=Contains}[2013 TO 2018]
与大多数本地参数不同,op 实际上不是由任何查询解析器(field)定义的,它是由字段类型定义的,在本例中为 DateRangeField。在上面的示例中,它将查找包含 (或等于) 范围2013到2018的索引范围的文档。文档中的多值重叠索引范围有效地合并。
有关 DateRangeField 示例用例,请参阅 Solr 的社区 wiki。