假设我有一个如下所示的文档映射字段
{
"template": {
"mappings":{
"template":{
"properties": {
"sth": {
"type": "long"
}
}
}
}
}
}
字段sth
是数组的类型。
我想检查字段sth
是否包含一个值,所以我编写了无痛的脚本,例如
doc['sth'].values.contains(1)
它失败了,我读了此article,了解它失败的原因,因为我必须通过一个
Long
改为contains
方法,因此我将无痛脚本更改为
doc['sth'].values.contains(1L)
它有效,但是一些进一步的实验使我更加疲惫。
脚本
doc['sth'].values[0] == 1
和doc['sth'].values[0] == 1L
两者都可以工作,好吧,我读了painless document,了解整数类型将被提升为长类型。
但是,根据文档,doc['sth'].values[0] == Integer.valueOf(156)
也可以工作
如果在原始类型值和引用类型值之间进行比较。
是否会引发错误?还是在某处自动取消装箱/装箱?
尽管如此,我还是写了剧本
doc['sth'].values[0] instanceof Long
和doc['sth'].values[0] instanceof long
,
两者都可以工作并返回true。
无痛数组类型是存储原始类型还是装箱引用类型?
最后,来到主题问题,在无痛脚本的Array contains方法的幕后,无痛到底做了什么。
这只是我不负责任的猜测
Array::contains
是否具有contains(Object o)
之类的签名,并使用==
将参数与其存储进行比较?
但是,如果这是事实,为什么doc['sth'].values[0] == 1
成功,但是doc['sth'].values[0] == 1
失败了吗?
答案 0 :(得分:1)
values
实际上是ScriptDocValues
类型(AbstractList
的抽象子类)。对于用long
键入的字段,实际的具体实现是ScriptDocValues.Longs
。
因此,为了回答您的问题,在内部,.contains()
方法将仅委派给AbstractCollection.contains()
,后者将在内部调用.equals()
。这就是doc['sth'].values.contains(1)
成功而doc['sth'].values.contains(1L)
失败的原因。
如您所见,这些值在内部存储在long
数组(原始类型)中。但是,get()
方法返回Long
(装箱的类型)以满足AbstractList
的约定,而getValue()
返回从调用中取消装箱的原语long
到get()
。这就是doc['sth'].values[0] == 1
和doc['sth'].values[0] == 1L
都成功的原因。
如果您致电get()
并且没有文档值,则会收到IllegalStateException
声明应该...
使用doc []。size()== 0检查文档是否缺少字段!