что именно безболезненно делать под капотом безболезненного сценария Array содержит метод - PullRequest
0 голосов
/ 30 сентября 2019

Предположим, что у меня есть поле отображения документа, как показано ниже

{
    "template": {
        "mappings":{
            "template":{
                "properties": {
                    "sth": {
                        "type": "long"
                    }
                }
            }
        }
    }
}

Поле sth - это тип массива.

Я хочу проверить, содержит ли поле sthзначение или нет, поэтому я пишу безболезненный скрипт типа doc['sth'].values.contains(1)

Не удалось, и я прочитал эту статью , понимаю, почему это не удалось, так как я должен передать Long вметод contains, поэтому я изменяю свой безболезненный сценарий на doc['sth'].values.contains(1L)

. Он работает, но некоторые дальнейшие эксперименты исчерпывают меня больше.

Сценарий

doc['sth'].values[0] == 1и doc['sth'].values[0] == 1L

оба могут работать, хорошо, я прочитал безболезненный документ , понимая, что целочисленный тип будет преобразован в длинный тип.

Но doc['sth'].values[0] == Integer.valueOf(156)также может работать, однако, согласно документу

Если проводится сравнение между значением примитивного типа и значением ссылочного типа.

Должно ли это вызвать ошибку? Или автоматически происходит распаковка / упаковка?

Тем не менее, я написал сценарий doc['sth'].values[0] instanceof Long и doc['sth'].values[0] instanceof long, оба могут работать и возвращать true.

Является ли тип безболезненного массива типом примитива, илиссылочный тип бокса?

Наконец, возникает вопрос о том, что именно делает безболезненно под капотом безболезненного скрипта, содержащего метод Array.

Это просто мое безответственное предположение

Есть ли у Array::contains сигнатура, подобная contains(Object o), и использовать == для сравнения параметра с его хранилищем?

Но если это правда, почему doc['sth'].values[0] == 1 успешен, но doc['sth'].values[0] == 1 терпит неудачу?

1 Ответ

1 голос
/ 30 сентября 2019

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(), а значение doc отсутствует, вы получите IllegalStateException с указанием, что вы должны ...

используйте doc []. Size () == 0, чтобы проверить, нет ли в документе поля!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...