Pythonランキング検索エンジンの実装(パート2)

前のパートでは、インデックスを作成しましたが、それに対してクエリを実行することはできません。 これについては、この記事で説明します。



インデックスクエリの実行



そのため、処理するクエリには2種類あります。クエリ内の少なくとも1つの単語がドキュメントに表示される標準クエリと、すべてのクエリワードが同じ順序でドキュメントに表示されるフレーズ付きクエリです。



ただし、開始する前に、インデックスの作成時にドキュメントを処理したのと同じ方法でリクエストを処理し、すべての単語を変換し、すべての文字を小文字にし、句読点を削除することをお勧めします。 些細なことなのでこれには触れませんが、リクエストを実行する前に行わなければなりません。



注:以下のすべてのコード例では、各関数は「invertedIndex」という変数を使用します。これは、記事の前の部分で生成されます。 以下で何が起こっているかを完全に理解するために、 GitHubで最終結果を見ることができます



最初に標準クエリを実装します。 それらを実装する簡単な方法は、クエリを単語(上記のようにマーカー)に分割し、各単語のリスト、それらが出現するドキュメントを取得し、これらすべてのリストを結合することです。 これは、1つの単語に対してクエリを実行する方法です。



def one_word_query(self, word): pattern = re.compile('[\W_]+') word = pattern.sub(' ',word) if word in self.invertedIndex.keys(): return [filename for filename in self.invertedIndex[word].keys()] else: return []
      
      





このコードは非常に単純です。 ここで行うことは、正規表現を使用して入力を処理し、インデックス内のその単語のハッシュテーブル内のすべてのキーのリスト(単語が出現するファイル名のリスト)を返すことです。



これで、標準クエリは非常に単純な拡張機能です。 ここに示すように、リストを単純に集約およびマージします。



 def free_text_query(self, string): pattern = re.compile('[\W_]+') string = pattern.sub(' ',string) result = [] for word in string.split(): result += self.one_word_query(word) return list(set(result))
      
      





クエリ内のすべての単語が最終リストに表示されるようにするクエリを実装する場合は、集計内の単語を含む個々のクエリの結果を結合する代わりに、共通部分を使用する必要があります。 これは非常に簡単なことであり、読者の演習として残しておきます。



クエリの最後のタイプはフレーズクエリです。これは、ドキュメント内の正しい語順を保証する必要があるため、もう少し複雑です。 このリクエストのコードは次のとおりです(後で説明します)。



 def phrase_query(self, string): pattern = re.compile('[\W_]+') string = pattern.sub(' ',string) listOfLists, result = [],[] for word in string.split(): listOfLists.append(self.one_word_query(word)) setted = set(listOfLists[0]).intersection(*listOfLists) for filename in setted: temp = [] for word in string.split(): temp.append(self.invertedIndex[word][filename][:]) for i in range(len(temp)): for ind in range(len(temp[i])): temp[i][ind] -= i if set(temp[0]).intersection(*temp): result.append(filename) return self.rankResults(result, string)
      
      





そのため、最初に入力リクエストのテキストを再度処理します。 次に、入力内の各単語に対してクエリから1つの単語を実行し、これらの各結果リストを共通リストに追加します。 次に、「setted」というセットを作成します。これは、最初のリストと他のすべてのリストの交差を受け入れ(本質的に、すべてのリストの交差を取得します)、中間結果を残します。すべてのクエリワードを含むすべてのドキュメントのセットです。



次に、中間結果を確認する必要があります。 したがって、中間結果の各リストについて、最初に入力クエリ内の各単語の位置のリストのリストを作成します。 次に(注意!)2つのネストされたforループを使用して、リストのリストを反復処理します。 各リストの各位置について、リストiを減算します。これは、リストのリストをたどるときに1ずつ増加します。 したがって、Pythonのリストは順序を維持するため、このリストのリストには、元のクエリの各単語の位置リストが元のクエリの単語順に含まれていることに注意してください。 次に、これらの単語が正しい順序であり、位置の各リストの各位置から整数iを減算し、次の位置のリストを通過するたびにiが1増加する場合、これらのフレーズが中間結果にある場合、これらの変更されたリストリストのすべての共通部分は、少なくとも1つの長さでなければなりません。



例を挙げましょう:



リクエストのフレーズが「ケーキは嘘です」としましょう。 ここで、特定のファイルについて、各単語の位置が次のとおりであると仮定します。

 : [19, 35, 12] : [179, 36, 197] : [221, 37, 912]
      
      





現在、リストのリストは次のとおりです。

 [[19, 35, 12], [179, 36, 197], [221, 37, 912]]
      
      





ここで、各リストの各項目からiを減算します。iは、最初のリストでは0、2番目のリストでは1、3番目のリストでは2などです。

 [[19, 35, 12], [178, 35, 196], [219, 35, 910]]
      
      





ここで、項目番号35の値が残っているすべてのリストの共通部分を取得した後、「ケーキは嘘です」というフレーズがファイルにあると判断できます。 これは事実です。最初のリストを見ると、シーケンス「35、36、37」がフレーズを示していることがわかります。



自分で実装できるクエリパラメータは他にもたくさんあります(インスピレーションについてはGoogleの高度な検索をご覧ください)。 それらのいくつかを検索エンジンに実装してみることができます。



最後の手順は、クエリパーサーを実装することです。これにより、さまざまな種類のクエリを組み合わせて1つの結果セットを取得できます。 たとえば、Googleで「cake」のようなものを入力するには、クエリ全体(クエリ全体)とクエリフレーズ(「this is a lie」)を組み合わせます。 これも非常に簡単です:区切り記号(たとえば、引用符)を使用して、特定の種類のクエリを示し、小さなクエリを個別に実行し、これらの結果セットをすべて走査して、ドキュメントの最終リストを取得します。



次の最終パートでは、結果のランキングについて説明し、結論を導きます。



All Articles