2015-12-14 3 views
2

У меня есть несколько документов в Cloudant, у которых есть поле идентификатора строки типа. Идентификатор может быть простой строкой, например «aaa», «bbb» или номером, сохраненным в виде текста, например. «111», «222» и т. Д. Мне нужно иметь возможность полнотекстового поиска с использованием вышеуказанного поля, но я столкнулся с некоторыми проблемами.Cloudant - Поиск диапазона Lucene с использованием чисел, сохраненных как текст

Если предположить, что у меня есть два документа, имеющие ID = "ааа" и ID = "111", то поиск с запросом:

  • ID: ааа
  • ID: "ааа"
  • ID : [ААА ZZZ]
  • ID: [ "ААА" до "ZZZ"]

возвращает первый документ, как и ожидалось

  • ID: 111

возвращает ничего, но

  • ID: "111"

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

К сожалению, при поиске диапазона:

  • ID: [111 TO 999]
  • ID: [ "111" В "999"]

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

UPDATE:

Индекс функции:

function(doc){ 
    if(!doc.ID) return; 
    index("ID", doc.ID, { index:'not_analyzed_no_norms', store:true }); 
} 

Изменение индекса проанализирован не помогает. Сам анализатор ключевое слово, но изменение на стандарт тоже не помогает.

UPDATE 2

Просто добавить еще некоторый контекст, потому что я думаю, что я пропустил один ключевой момент. Индексирование поля I будет выполняться с использованием диапазонов, и минимальные и максимальные значения могут быть предоставлены пользователем. Таким образом, возможно, что один из них будет содержать номер в виде строки, в то время как другой будет стандартным нечисловым текстом. Например, найдите весь документ, где ID> = "11" и ID < = "foo".

Предположим, что в базе данных содержатся документы с идентификаторами «1», «5», «альфа», «бета», «гамма», этот запрос должен возвращать «5», «альфа», «бета». Обратите внимание, что «5» должно быть действительно возвращено, потому что строка «5» больше строки «11».

+0

Есть ли шанс, что вы можете поделиться своей функцией Map? – ukmadlz

+0

Нет функции отображения, так как это полный текстовый индекс. Вопрос обновлен и содержит тело функции индекса. –

+0

@ArekDygas вы можете прокомментировать, почему вы хотите сделать такой запрос диапазона для строк? Мне кажется, что если сортировка и запрос диапазона важны, вы будете использовать числовые значения. – Raj

ответ

2

Наша команда только что пришла к обходному решению. Нам удалось получить правильные результаты, добавив некоторый произвольный символ, например. 'a' до значения верхнего диапазона и путем введения дополнительного условия поиска, чтобы исключить документы, имеющие идентификатор между верхним значением диапазона и верхним значением диапазона + 'a'.

При поиске диапазона

ID: [Х -Y]

фактический запрос будет

(ID: [X Я.] И -ID: {У Я.])

Например, чтобы найти документы, имеющие идентификатор между 23 и 758, мы выполняем

(ID: [23, с 758a] и -ID: {758 к 758a]).

1

Вы можете получить оба документы возвращены так:

q=ID:["111" TO "CCC"] 

Вот живой пример работает:

https://rajsingh.cloudant.com/facetrangetest/_design/ddoc/_search/f?q=ID:[%22111%22%20TO%20%22CCC%22]

я нашел что-то изворотливый. Кажется, что запросы диапазона по строкам работают только в том случае, если хотя бы одно из значений диапазона является строкой. Запрос на ID:["111" TO "555"] тоже ничего не возвращает, так что, возможно, это как-то разрешает числовой запрос? Может быть ошибка.

+0

Да - ["111" TO "CCC"] будет работать, но, как отмечено в ответе Майе Шариповой, не поможет в моем случае ... К сожалению, я также думаю, что это ошибка. –

2

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

"analyzer": "keyword", 
"index": "function(doc){\n if(!doc.ID) return;\n index(\"ID\", doc.ID, {store:true });\n} 

Чтобы получить вам документ с _id «111», используйте следующий запрос диапазона:

curl -X GET "http://.../facetrangetest/_design/ddoc/_search/f?q=ID:\[111%20TO%A\]" 

Если вы используете запрос q=ID:\[111%20TO%20999\], Cloudant поиск видеть номера на обоих размер диапазона, будет интерпретировать это как NumericRangeQuery; и поскольку ваш идентификатор «111» является строкой, он не будет частью возвращенных результатов. Включение строки в запрос [111% 20TO% 20A] заставит Cloudant интерпретировать его как запрос диапазона для строк.

+0

Я действительно использую анализатор ключевых слов. И в отношении [111 TO A] - это работает, но, к сожалению, не поможет в моем случае, так как я не буду искать диапазоны, как 2 TO 123 ... Я думал, что Cloudant должен интерпретировать типы диапазонов на основе фактических тип поля, но, по-видимому, это не так, как это работает ... –

+0

Невозможно интерпретировать типы диапазонов для фактического типа поля, поскольку невозможно знать тип поля, так как CouchDb и Apache Lucene могут иметь разные типы для то же имя поля. –

1

Это также может быть достигнуто с использованием регулярных выражений в запросах. Что-то линия это:

curl -X POST "https://.../facetrangetest/_design/ddoc/_search/f" -d '{"q":"ID:/<23-758>/"}' | jq .

Это означает, что регулярные выражения, чтобы получить все документы с ID поля от 23 до 758. Slashes: // используются, чтобы приложить регулярное выражение; интервал заключен внутри <>.

+0

Я думаю, что это работает только для чисел, поэтому, к сожалению, это не покрывает мои потребности ... –

+0

Это работает для строк. –

+0

Хм. Когда я меняю запрос на/<1-a> /, я получаю «синтаксическую ошибку интервала в позиции 4». Закрытие текста в двойных кавычках (/ <1-"a"> /) тоже не помогает (ошибка в позиции 6). Не могли бы вы поделиться примером запроса, который работает со строками? –

Смежные вопросы