XQuery Полнотекстовый поиск по смешанному контенту
Ниже приведена структура XML - (я дал очень маленький фрагмент всего документа с ограниченными данными. У меня есть база данных XML объемом 6 ГБ с соответствующим индексом FULL TEXT.)
<Docs>
<Doc>
<Chap>No - 1</Chap>
<Desc>
<Notes>
<Para t="sn">departmental report</Para>
</Notes>
<Notes>
<Para t="sn">The equiry commission is good.</Para>
</Notes>
<Notes>
<Para t="sn">departmental process</Para>
<Para t="ln">The enquiry report for the bomb blast is yet to come.<bL/>
<bL/>The department working on this is quite lazy.</Para>
</Notes>
</Desc>
</Doc>
<Doc>
<Chap>No - 2</Chap>
<Desc>
<Notes>
<Para t="sn">Enquiry Processes Report</Para>
<Para t="ln">The enquiry process is very simple.<bL/>
<bL/>With proper guidance anybody can handle the commission easily.<bL/>
<bL/>
</Para>
</Notes>
<Notes>
<Para t="sn">Enquiry - Departmental</Para>
</Notes>
</Desc>
</Doc>
<Doc>
<Chap>No - 3</Chap>
<Desc>
<Notes>
<Para t="sn">Physics Department</Para>
</Notes>
<Notes>
<Para t="sn">Working process of physics department is quite lengthy</Para>
<Para t="ln">Even after proper enquiry, I was told nothing.<bL/>
<bL/>This was like a bomb blast.</Para>
</Notes>
<Notes>
<Para t="sn">Departmental enquiry.</Para>
<Para t="ln">There should be a departmental enquiry for this wrong process.</Para>
</Notes>
</Desc>
</Doc>
</Docs>
Теперь я хочу все эти Chap
узлы, содержащие все слова "ведомственный", "запрос" и "отчет".
До сих пор я не могу получить их, используя различные комбинации. Одна из моих попыток -
for $x in ft:search("Docs", ("departmental enquiry report"), map{'mode':='all words'})/ancestor::*:Para
return $x/ancestor::Chap
Может ли какое-либо тело руководить мной в этом?
2 ответа
Полнотекстовый индекс BaseX ссылается на все термины на уровне текстового узла. Это означает, что все ваши слова должны находиться в одном текстовом узле.
Если вы хотите воспользоваться полнотекстовым запросом и найти все слова, которые встречаются ниже определенного элемента, вы можете попробовать следующий запрос:
let $words := ("departmental enquiry report")
for $doc in db:open("Docs")//Doc[.//text() contains text { $words } any word]
where $doc[string-join(.//text(), ' ') contains text { $words } all words]
return $doc/Chap
Первый contains text
выражение будет переписано в запросе индекса. Он вернет все тексты, которые возвращают любое из искомых слов. Содержит текстовое выражение в where
Предложение будет отфильтровывать все узлы, которые не содержат все ваши условия запроса. С string-join(.//text(), ' ')
все текстовые узлы под элементом Doc будут объединены, и поиск будет выполнен по объединенной строке.
Следующее эквивалентное представление запроса должно дать те же результаты:
let $words := ("departmental enquiry report")
for $x in ft:search("Docs", $words, map { 'mode': 'any word' })/ancestor::*:Doc
where ft:contains(string-join($x//text(), ' '), $words, map { 'mode': 'all words' })
return $x/Chap
ft:search
и почему это не решит проблему
Изучив полнотекстовую документацию по BaseX, вы поймете, что второй аргумент в ft:search
должна быть последовательность слов:
ft:search($db as xs:string, $terms as item()*, $options as item()) as text()*
Итак, ваш запрос должен выглядеть примерно так
for $x in ft:search("Docs", ("departmental", "enquiry", "report"), map{'mode':='all words'})/ancestor::*:Para
return $x/ancestor::Chap
Все же это все равно не решит вашу проблему, так как эта функция
[re] превращает все текстовые узлы из полнотекстового индекса базы данных
$db
которые содержат указанный$terms
,
Другими словами: все эти слова должны были бы встречаться в одном текстовом узле, но они распределены по нескольким в вашем примере ввода (во всем <Doc/>
узел).
Использование стандартного полного текста XQuery
Я должен был угадать из ввода и слов, которые вы ищете, что вы действительно хотите найти <Doc/>
узлы, которые содержат все эти три слова.
for $document in doc("Docs")/Docs/Doc
where $document contains text { 'departmental', 'enquiry', 'report' } all words
return $document/Chap
Это позволит получить все документы, применить к ним полнотекстовый поиск и, наконец, вернуть узел главы документа.
Знать
- Я удалил подстановочный знак пространства имен, поскольку в ваш пример документа не включены пространства имен
- создать полнотекстовый индекс (если вы еще этого не сделали), который значительно повысит производительность.