Подзапросы в MySQL с полнотекстовыми запросами - PullRequest
1 голос
/ 22 декабря 2011

Я пытаюсь запросить базу данных.У меня уже есть файл, который включает в себя некоторые первичные ключи из всей этой базы данных.Теперь я хочу отфильтровать эти первичные ключи и получить только те первичные ключи, которые также соответствуют «другому условию».Мои первичные ключи связаны с рефератами в базе данных.Тезисы полнотекстовой индексации.Теперь я хочу рассмотреть рефераты, используя заданные первичные ключи, найти мои «другие условия (термины)» в этих рефератах и, если они присутствуют, я хочу извлечь их первичные ключи (которые будут такими же из файла).Мое "другое условие" - это другой файл со списком терминов.Я хочу получить рефераты, которые содержат эти термины в заданных первичных ключах.

Мой полнотекстовый поиск выглядит примерно так:

while(<FILE1>){
$PK = $_;
foreach $foo(@foo){
my $sth = $dbh->prepare(qq{
   SELECT value
     FROM value_table
    WHERE MATCH (column_text_indexed) AGAINST (? IN BOOLEAN MODE)
}) AND primary_key=$PK;

$sth->execute(qq{+"$foo"});
}
}

, где $ PK идет из списка первичных ключей, которые у меня уже есть.$ foo будет списком условий (условие 2), которые я ищу.

Обычно я могу выполнить этот номер запроса $ PK, умноженный на число $ foo.Но я кое-что узнал об оптимизации, выполнив подзапрос, где я не буду выполнять свой запрос # $ PK times # $ foo.Это избавит от внутреннего цикла, но все равно сформирует комбинацию каждого $ PK с каждым термином в файле 2, который является @foo.Что-то вроде следующего:

while(<FILE1>){
$PK = $_;
   my $sth = $dbh->prepare(qq{
   SELECT value
     FROM value_table
    WHERE MATCH (column_text_indexed) AGAINST (**SUB QUERYING HERE**)
}) AND primary_key=$PK;

$sth->execute(qq{+"$foo"});

}

Просто я не знаю, как это сделать.Я могу ошибаться с синтаксисом.Я хочу знать, как написать код для полнотекстового поиска, а также подзапрос.Я надеюсь, что это будет эффективнее, чем прямой запрос комбинаций.Любая помощь с благодарностью.

Ответы [ 3 ]

1 голос
/ 22 декабря 2011

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

my $against = join ' ', map {qq/"$_"/} @foo;
while (my $PK = <FILE1>) {
    chomp $PK;

    my $sth = $dbh->prepare(qq{
       SELECT value
         FROM value_table
        WHERE primary_key = ?
          # no '+' so it can match against at least one of the words in the list
          AND MATCH (column_text_indexed) AGAINST (? IN BOOLEAN MODE)
    });
    $sth->execute($PK, $against);

Обновление

Я пересмотрел его и полностью удалил запрос из циклов.

my @primary_keys;
while (my $PK = <FILE1>) {
    chomp $PK;
    push @primary_keys, $PK;
}

my $PK_list = join ',', map {qq/'$_'/} @primary_keys;
my $against = join ' ', map {qq/"$_"/} @foo;

my $sth = $dbh->prepare(qq{
   SELECT value
     FROM value_table
    # placeholders can only represent single scalar values so $PK_list can't be bound
    WHERE primary_key IN ($PK_list)
      # no '+' so it can match against at least one of the words in the list
      AND MATCH (column_text_indexed) AGAINST (? IN BOOLEAN MODE)
});
$sth->execute($against);

# continue with fetching the rows
...;
1 голос
/ 29 декабря 2011

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

для всех терминов в PK, получайте реферат в виде строковой переменной:

для каждого термина в массиве / списке: найтитермин в строковой переменной, содержащий абстрактный.Если найдено, добавьте PK в новый файл.

продолжите со следующего pk.

, если не найдено, продолжите следующий термин в массиве / списке.

1 голос
/ 22 декабря 2011

Ваш синтаксис выглядит хитроумно.Я думаю, вы имели в виду:

while(<FILE1>){
    $PK = $_;

    foreach $foo (@foo){

         my $sth = $dbh->prepare(qq{
                     SELECT value
                     FROM value_table
                     WHERE MATCH (column_text_indexed)
                       AGAINST (**SUB QUERYING HERE**)
                     AND primary_key=$PK });           # '})' after AND clause

         $sth->execute(qq{ $foo });
     }
}

Но почему бы не сделать $PK дополнительным аргументом в этом случае (и использовать лучшие практики)?:

while ( my $PK = <FILE1> ) {

    chomp $PK;  # Remove trailing newline

    foreach my $foo ( @foo ) {   # Lexical $foo

        my $sth = $dbh->prepare( qq{
                         SELECT value
                         FROM value_table
                         WHERE MATCH (column_text_indexed)
                           AGAINST (**SUB QUERYING HERE**)
                         AND primary_key=? });             # Extra placeholder

        $sth->execute( $foo, $PK );
    }
}
...