Нечеткий поиск с помощью Cloudant/Lucene не дает результатов

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

http://wetten.cloudant.com/regelingen/_design/RegelingInfo/_search/regeling?q=burgerlijke

Когда я пытаюсь сделать свои поиски нечеткими, все идет не так:

http://wetten.cloudant.com/regelingen/_design/RegelingInfo/_search/regeling?q=burgerlijke~

Внезапно вернуть 0 результатов. Как это может быть?


Редактировать:

Конструкторский документ:

{"_id": "_design/RegelingInfo",
    "_rev": "11-20993b8c49d8bcc1cd4fde58e5f40b27",
    "views": {
        "all": {
            "map": "function(doc) { \n  if (doc._id.lastIndexOf('BWB', 0) === 0 ){\n   emit( null, doc._id )\n  }\n}"
        }
    },
    "lists": {},
    "shows": {},
    "language": "javascript", "filters": {}, "updates": {}, "indexes": {
    "regeling": {
        "analyzer": {
            "name": "dutch",
            "stopwords": ["wet", "regeling", "besluit"]
        },
        "index": "function(doc) {\n    var globalString = new Array();\n    index(\"displayTitle\", doc.displayTitle, {\"store\": \"yes\"});\n    globalString.push(doc.displayTitle);\n    /*index(\"officieleTitel\", doc.officieleTitel, {\"store\": \"no\"});*/\n    globalString.push(doc.officieleTitel);\n    /*index(\"bwbid\", doc._id);*/\n    globalString.push(doc._id);\n    index(\"regelingSoort\", doc.regelingSoort, {\"store\": \"no\"});\n    if (doc.citeertitels) {\n        for (var i = 0; i < doc.citeertitels.length; i++) {\n            /*index(\"citeertitel\", doc.citeertitels[i].titel, {\"store\": \"no\"});*/\n            globalString.push(doc.citeertitels[i].titel);\n        }\n    }\n    if (doc.afkortingen) {\n        for (var i = 0; i < doc.afkortingen.length; i++) {\n            /*index(\"afkorting\", doc.afkortingen[i], {\"store\": \"no\"});*/\n            globalString.push(doc.afkortingen[i]);\n        }\n    }\n    if (doc.nietOfficieleTitels) {\n        for (var i = 0; i < doc.nietOfficieleTitels.length; i++) {\n            /*index(\"nietOfficieleTitel\", doc.nietOfficieleTitels[i], {\"store\": \"no\"});*/\n            globalString.push(doc.nietOfficieleTitels[i]);\n        }\n    }\n    if (doc.xml) {\n        /* Remove tags to get inner text*/\n        index(\"innerText\", doc.xml.replace(/<[^>]*>/g, \"\"), {\"store\": \"no\"});\n    }\n    index(\"default\", globalString.join(\" \"), {\"store\": \"no\"});\n}"
    }
}}

Функция форматированного индексирования:

function(doc) {
    var globalString = new Array();
    index("displayTitle", doc.displayTitle, {"store": "yes"});
    globalString.push(doc.displayTitle);
    /*index("officieleTitel", doc.officieleTitel, {"store": "no"});*/
    globalString.push(doc.officieleTitel);
    /*index("bwbid", doc._id);*/
    globalString.push(doc._id);
    index("regelingSoort", doc.regelingSoort, {"store": "no"});
    if (doc.citeertitels) {
        for (var i = 0; i < doc.citeertitels.length; i++) {
            /*index("citeertitel", doc.citeertitels[i].titel, {"store": "no"});*/
            globalString.push(doc.citeertitels[i].titel);
        }
    }
    if (doc.afkortingen) {
        for (var i = 0; i < doc.afkortingen.length; i++) {
            /*index("afkorting", doc.afkortingen[i], {"store": "no"});*/
            globalString.push(doc.afkortingen[i]);
        }
    }
    if (doc.nietOfficieleTitels) {
        for (var i = 0; i < doc.nietOfficieleTitels.length; i++) {
            /*index("nietOfficieleTitel", doc.nietOfficieleTitels[i], {"store": "no"});*/
            globalString.push(doc.nietOfficieleTitels[i]);
        }
    }
    if (doc.xml) {
        /* Remove tags to get inner text*/
        index("innerText", doc.xml.replace(/<[^>]*>/g, ""), {"store": "no"});
    }
    index("default", globalString.join(" "), {"store": "no"});
}

person Maarten    schedule 05.12.2013    source источник
comment
Пожалуйста, добавьте свой код здесь, тогда только мы найдем ошибки в вашей программе.   -  person Mr.G    schedule 05.12.2013
comment
Добавил свой дизайн-документ!   -  person Maarten    schedule 05.12.2013


Ответы (3)


Вы можете видеть, что делает анализатор;

curl 'http://wetten.cloudant.com/_search_analyze -d '{"analyzer":"dutch","text":"burgerlijke"}'

который возвращается;

{"tokens":["burger"]}

Этот запрос;

curl 'https://wetten.cloudant.com/regelingen/_design/RegelingInfo/_search/regeling?q=burger~'

возвращает 575 строк.

Это довольно неловко, однако, это должно быть сделано для вас. Мы рассмотрим это.

person Robert Newson    schedule 05.12.2013
comment
Роберт Ньюсон предположил, что это особенность Lucene, потому что нечеткие запросы не анализируются. (?) ' в конце вашего запроса означает что-то особенное? - person Maarten; 06.12.2013
comment
Нет, это просто шум, я использую zsh, а не bash, что заставляет меня правильно цитировать вещи, поэтому эта строка взята из строки вроде curl 'url here'. - person Robert Newson; 07.12.2013
comment
Мы получаем совпадения, если пользователь выполняет определение основы, это моя точка зрения. С конечной точкой _search_analyze вы можете автоматизировать это. Это неудобно, и я хотел бы улучшить его, если только не окажется, что мы затрагиваем фундаментальную вещь Lucene. - person Robert Newson; 07.12.2013

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

DutchAnalyzer, как и в большинстве языковых анализаторов, включает в себя парадигму для сопоставления альтернативных форм слов с одним и тем же корневым словом (т. е. основой). Однако подстановочные знаки, нечеткие, регулярные выражения и т. д. запросы не анализируются. TermQueries есть.

Таким образом, если burgerlijke значительно сокращается в индексе (это кажется достаточно вероятным из-за незнания языка), вполне возможно, что расстояние редактирования между версией с основой и версией без основы просто слишком велико. здорово увидеть матч. Если термин в индексе был, скажем, «гамбургер», расстояние редактирования равно 5 от термина нечеткого запроса «burgerlijke», что слишком далеко для получения результата.

Как правило, стеммеры плохо работают с любыми . MultiTermQuery.

person femtoRgon    schedule 05.12.2013
comment
Это странно — вы говорите, что термин запроса не анализируется, а возвращается к своей основе? Это желаемое поведение? Проба стебля (бургера); запрос burger~ возвращает inburgers, burgers и burgerlijk. - person Maarten; 05.12.2013
comment
Ах, проиндексированные слова, конечно, основаны, а не запрос! Значит, нельзя совместить нечеткий оператор с языковыми анализаторами? - person Maarten; 05.12.2013

Да, все дело в анализе. Вот полезная (но недокументированная) конечная точка API, которая поможет отладить эти вещи. Замените свое собственное имя пользователя/учетные данные, но тогда это просто:

curl 'https://malortmike.cloudant.com/_search_analyze?analyzer=dutch&text="burgerlijke"'
{"tokens":["burger"]}

curl -u 'malortmike:secret' 'https://malortmike.cloudant.com/_search_analyze?analyzer=standard&text="burgerlijke"'
{"tokens":["burgerlijke"]}

Интересно посмотреть на разные анализаторы в действии.

person Mike Miller    schedule 05.12.2013