在 painless 脚本的 Array contains 方法的幕后,painless 到底做了什么
what exactly does painless do under the hood of painless script's Array contains method
假设我有一个如下所示的文档映射字段
{
"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,了解到整数类型将被提升为long类型。
但是doc['sth'].values[0] == Integer.valueOf(156)
也可以,但是根据文档
If a comparison is made between a primitive type value and a reference type value.
它应该引发错误吗?或者自动 unboxing/boxing 发生在某处?
尽管如此,我写了脚本
doc['sth'].values[0] instanceof Long
和 doc['sth'].values[0] instanceof long
,
两者都可以工作 return true.
无痛数组类型存储的是原始类型,还是装箱引用类型?
最后,来到主题问题,painless 脚本的 Array contains 方法背后到底做了什么。
这只是我不负责任的猜测
是Array::contains
有一个类似contains(Object o)
的签名,用==
来
将参数与其存储进行比较?
但如果这是真的,为什么 doc['sth'].values[0] == 1
成功但 doc['sth'].values[0] == 1
失败?
values
实际上是 ScriptDocValues
(an abstract subclass of AbstractList
). For a field typed with long
, the actual concrete implementation is ScriptDocValues.Longs
.
类型
因此,为了回答您的问题,在幕后,.contains()
方法将简单地委托给 AbstractCollection.contains()
,后者在幕后调用 .equals()
。这就是 doc['sth'].values.contains(1)
失败而 doc['sth'].values.contains(1L)
成功的原因。
如您所见,这些值在内部存储在 long
数组(原始类型)中。然而,get()
方法returns一个Long
(盒装类型)为了满足AbstractList
契约和getValue()
returns一个原始long
从对 get()
的调用中拆箱。这就是 doc['sth'].values[0] == 1
和 doc['sth'].values[0] == 1L
都成功的原因。
如果您调用 get()
并且没有文档值,您将得到一个 IllegalStateException
说明您应该...
use doc[].size()==0 to check if a document is missing a field!
假设我有一个如下所示的文档映射字段
{
"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,了解到整数类型将被提升为long类型。
但是doc['sth'].values[0] == Integer.valueOf(156)
也可以,但是根据文档
If a comparison is made between a primitive type value and a reference type value.
它应该引发错误吗?或者自动 unboxing/boxing 发生在某处?
尽管如此,我写了脚本
doc['sth'].values[0] instanceof Long
和 doc['sth'].values[0] instanceof long
,
两者都可以工作 return true.
无痛数组类型存储的是原始类型,还是装箱引用类型?
最后,来到主题问题,painless 脚本的 Array contains 方法背后到底做了什么。
这只是我不负责任的猜测
是Array::contains
有一个类似contains(Object o)
的签名,用==
来
将参数与其存储进行比较?
但如果这是真的,为什么 doc['sth'].values[0] == 1
成功但 doc['sth'].values[0] == 1
失败?
values
实际上是 ScriptDocValues
(an abstract subclass of AbstractList
). For a field typed with long
, the actual concrete implementation is ScriptDocValues.Longs
.
因此,为了回答您的问题,在幕后,.contains()
方法将简单地委托给 AbstractCollection.contains()
,后者在幕后调用 .equals()
。这就是 doc['sth'].values.contains(1)
失败而 doc['sth'].values.contains(1L)
成功的原因。
如您所见,这些值在内部存储在 long
数组(原始类型)中。然而,get()
方法returns一个Long
(盒装类型)为了满足AbstractList
契约和getValue()
returns一个原始long
从对 get()
的调用中拆箱。这就是 doc['sth'].values[0] == 1
和 doc['sth'].values[0] == 1L
都成功的原因。
如果您调用 get()
并且没有文档值,您将得到一个 IllegalStateException
说明您应该...
use doc[].size()==0 to check if a document is missing a field!