Oracle: как выполнить полнотекстовый поиск по XMLType? - PullRequest
4 голосов
/ 14 июня 2011

У меня есть приложение, хранящее XML в таблице Oracle как XMLType. Я хочу сделать полнотекстовый поиск по этим данным. В документации Oracle, в Полнотекстовый поиск по данным XML , рекомендуется использовать функцию SQL contains, которая требует индексации данных с индексом context. Беда в том, что, похоже, context индексы асинхронные , что не соответствует используемому мной сценарию использования, где мне нужно иметь возможность искать данные сразу после их добавления.

Можно ли сделать этот индекс каким-то синхронным? Если нет, какую другую технику я должен использовать для полнотекстового поиска на XMLType?

Ответы [ 2 ]

4 голосов
/ 15 июня 2011

Его нельзя сделать транзакционным (т. Е. Он не будет обновлять индекс, чтобы изменение было видно для последующего оператора в транзакции). Лучшее, что вы можете сделать - это обновить его при коммите (SYNC ON COMMIT), например:

create index your_table_x
    on your_table(your_column)
    indextype is ctxsys.context
    parameters ('sync (on commit)');

Текстовые индексы являются сложными вещами, и я был бы удивлен, если бы вы могли достичь транзакционного / ACID-совместимого текстового индекса (то есть транзакции A, вставляющей документы и имеющей те, которые видны в индексе для этой транзакции и не видны транзакции B до фиксации).

3 голосов
/ 15 июня 2011
  1. Вы можете обновлять индекс через регулярные промежутки времени, в стиле cron . В худшем случае вы можете обновлять индекс после каждого обновления таблицы, используя sync_index, на котором построен индекс. Например: EXEC CTX_DDL.SYNC_INDEX('your_index'); Я не большой поклонник этой техники из-за сложности, которую она вводит. В дополнение к cron-подобному аспекту вам приходится иметь дело с фрагментацией индекса, которая может потребовать от вас время от времени полного обновления. Обновление: вместо обновления индекса через регулярные промежутки времени, вы можете обновить его при коммите, как , предложенный Гэри , который действительно то, что вы ищете.

  2. Вы можете выполнить простой текстовый поиск в документе XML, как если бы вы выполняли Ctrl-F с XML в текстовом редакторе. Во многих случаях это не дает ожидаемого результата, поскольку пользователям все равно, будет ли искомая строка использоваться в имени элемента, имени атрибута или пространстве имен. Но если этот метод работает для вас, сделайте это: он прост и довольно быстр. Например:

    select count(*) from your_table d
    where lower(d.your_column.getClobVal()) like '%gaga%';
    
  3. Использование existsNode() в предложении where, как в примере ниже. Есть две потенциальные проблемы с этим. Во-первых, без правильных индексов, это медленнее, чем метод № 2, примерно в 2 раза в моем тестировании, и я не уверен, как создать индекс для неструктурированных данных, которые будут использоваться этим запросом. Во-вторых, вы будете выполнять поиск с учетом регистра, что часто не то, что вы хотите. И вы не можете просто вызвать XPath lower-case(), так как Oracle поддерживает только XPath 1.0.

    select * from your_table 
    where existsNode(your_column, '//text()[contains(., "gaga")]') = 1;
    
...