Azure Cognitive Search でのフルテキスト検索Full text search in Azure Cognitive Search

この記事は、Azure Cognitive Search における Lucene のフルテキスト検索のしくみについて理解を深める必要がある開発者を対象としています。This article is for developers who need a deeper understanding of how Lucene full text search works in Azure Cognitive Search. テキスト クエリに関して、Azure Cognitive Search はほとんどの状況で速やかに適切な結果を返します。しかし一見、間違っているのではないか、と思うような結果が返されることも皆無ではありません。For text queries, Azure Cognitive Search will seamlessly deliver expected results in most scenarios, but occasionally you might get a result that seems "off" somehow. このような状況では、Lucene による 4 段階から成るクエリ実行 (クエリ解析、字句解析、文書のマッチング、スコア付け) についての背景知識があると、具体的にどのような変更をクエリ パラメーターやインデックス構成に加えれば目的の結果が得られるかが特定しやすくなります。In these situations, having a background in the four stages of Lucene query execution (query parsing, lexical analysis, document matching, scoring) can help you identify specific changes to query parameters or index configuration that will deliver the desired outcome.

注意

Azure Cognitive Search では、フルテキスト検索に Lucene が使われていますが、Lucene の機能がそのままの形で統合されているわけではありません。Azure Cognitive Search uses Lucene for full text search, but Lucene integration is not exhaustive. Microsoft は、Azure Cognitive Search にとって重要なシナリオを実現する Lucene の機能を選んで公開、拡張しています。We selectively expose and extend Lucene functionality to enable the scenarios important to Azure Cognitive Search.

アーキテクチャの概要と図Architecture overview and diagram

フルテキスト検索クエリの処理は、クエリ テキストを解析して検索語を抽出することから始まります。Processing a full text search query starts with parsing the query text to extract search terms. 検索エンジンはインデックスを使って、一致する語句を含んだ文書を取得します。The search engine uses an index to retrieve documents with matching terms. 個々の検索語はしばしば分解され、新しい形に再構築されて、できるだけ広い範囲から "一致と見なす候補" が得られます。Individual query terms are sometimes broken down and reconstituted into new forms to cast a broader net over what could be considered as a potential match. その後、一致する個々の文書に割り当てられた関連度スコアに基づいて結果セットが並べ替えられます。A result set is then sorted by a relevance score assigned to each individual matching document. このようにランク順に並んだリストの先頭の結果が、呼び出し元のアプリケーションに返されます。Those at the top of the ranked list are returned to the calling application.

つまり、クエリの実行には次の 4 つの段階があります。Restated, query execution has four stages:

  1. クエリ解析Query parsing
  2. 字句解析Lexical analysis
  3. 文書検索Document retrieval
  4. ポイントの計算Scoring

以下の図は、検索要求の処理に使用されるコンポーネントを示しています。The diagram below illustrates the components used to process a search request.

Azure Cognitive Search における Lucene クエリ アーキテクチャの図

主なコンポーネントKey components 機能の説明Functional description
クエリ パーサーQuery parsers クエリ演算子から検索語を切り離し、検索エンジンに送るクエリ構造 (クエリ ツリー) を作成します。Separate query terms from query operators and create the query structure (a query tree) to be sent to the search engine.
アナライザーAnalyzers 検索語に対する字句解析を実行します。Perform lexical analysis on query terms. このプロセスには、検索語の変換、削除、拡大が伴う場合があります。This process can involve transforming, removing, or expanding of query terms.
IndexIndex 索引付けの対象文書から抽出した検索可能な語句を効率よく体系的に格納するデータ構造です。An efficient data structure used to store and organize searchable terms extracted from indexed documents.
検索エンジンSearch engine 転置インデックスの内容に基づいて、一致する文書を検索してスコア付けします。Retrieves and scores matching documents based on the contents of the inverted index.

検索要求の構造Anatomy of a search request

検索要求は、結果セットで返すべき内容を詳細に規定した仕様です。A search request is a complete specification of what should be returned in a result set. 最も単純な形式では、どのような種類の条件も含まれていない空のクエリです。In simplest form, it is an empty query with no criteria of any kind. しかしより現実的な例では、パラメーターや複数の検索語を伴うのが一般的です。場合によっては、検索範囲を特定のフィールドに限定したり、フィルター式や並べ替え規則が使われたりすることもあります。A more realistic example includes parameters, several query terms, perhaps scoped to certain fields, with possibly a filter expression and ordering rules.

次の例は、REST API を使用して Azure Cognitive Search に送信できる検索要求です。The following example is a search request you might send to Azure Cognitive Search using the REST API.

POST /indexes/hotels/docs/search?api-version=2020-06-30
{
    "search": "Spacious, air-condition* +\"Ocean view\"",
    "searchFields": "description, title",
    "searchMode": "any",
    "filter": "price ge 60 and price lt 300",
    "orderby": "geo.distance(location, geography'POINT(-159.476235 22.227659)')", 
    "queryType": "full" 
}

この要求に対して、検索エンジンは次のことを実行します。For this request, the search engine does the following:

  1. 価格が $60 以上 $300 未満の文書を抽出します。Filters out documents where the price is at least $60 and less than $300.
  2. クエリを実行します。Executes the query. この例では、検索クエリが "Spacious, air-condition* +\"Ocean view\"" という語句で構成されています (通常はユーザーが句読点を入力することはありませんが、この例では、アナライザーによる処理を説明するためにあえて含めています)。In this example, the search query consists of phrases and terms: "Spacious, air-condition* +\"Ocean view\"" (users typically don't enter punctuation, but including it in the example allows us to explain how analyzers handle it). このクエリの場合、検索エンジンは、searchFields に指定された description フィールドと title フィールドをスキャンし、"Ocean view" を "spacious" という語か、"air-condition" で始まる語に接する形で含んでいる文書を探します。For this query, the search engine scans the description and title fields specified in searchFields for documents that contain "Ocean view", and additionally on the term "spacious", or on terms that start with the prefix "air-condition". 明示的に必須指定 (+) されていない語句に関して、マッチング対象を任意 (既定) とするか、すべてとするかが、searchMode パラメーターで指定されています。The searchMode parameter is used to match on any term (default) or all of them, for cases where a term is not explicitly required (+).
  3. 検索結果として得られた一連のホテルは、特定の地理的位置に近い順に並べ替えられて、呼び出し元のアプリケーションに返されます。Orders the resulting set of hotels by proximity to a given geography location, and then returned to the calling application.

この記事では主に、"検索クエリ" ("Spacious, air-condition* +\"Ocean view\"") の処理について取り上げています。The majority of this article is about processing of the search query: "Spacious, air-condition* +\"Ocean view\"". フィルター処理と並べ替えについては取り上げません。Filtering and ordering are out of scope. 詳細については、Search API のリファレンス ドキュメントを参照してください。For more information, see the Search API reference documentation.

ステージ 1:クエリ解析Stage 1: Query parsing

前出のとおり、検索要求の最初の行がクエリ文字列です。As noted, the query string is the first line of the request:

 "search": "Spacious, air-condition* +\"Ocean view\"", 

クエリ パーサーは、検索語から演算子 (この例の *+) を切り離し、検索クエリを "サブクエリ" に分解します。次の種類のサブクエリがサポートされています。The query parser separates operators (such as * and + in the example) from search terms, and deconstructs the search query into subqueries of a supported type:

  • "単語検索": 独立した語を検索 (spacious など)term query for standalone terms (like spacious)
  • "フレーズ検索": 引用符で囲まれた語句を検索 (ocean view など)phrase query for quoted terms (like ocean view)
  • "プレフィックス検索": 語句 + プレフィックス演算子 *を検索 (air-condition など)prefix query for terms followed by a prefix operator * (like air-condition)

サポートされているクエリの種類すべての一覧については、Lucene のクエリ構文に関するページを参照してください。For a full list of supported query types see Lucene query syntax

文書が一致していると見なされるために検索条件との一致が "必須 (must)" であるのか "勧告 (should be)" であるのかは、サブクエリに関連付けられている演算子によって決まります。Operators associated with a subquery determine whether the query "must be" or "should be" satisfied in order for a document to be considered a match. たとえば、+"Ocean view"+ 演算子が指定されているので検索条件との一致が "必須" となります。For example, +"Ocean view" is "must" due to the + operator.

クエリ パーサーは、サブクエリを "クエリ ツリー" (クエリを表す内部的な構造) に再構築して検索エンジンに渡します。The query parser restructures the subqueries into a query tree (an internal structure representing the query) it passes on to the search engine. クエリ解析の第 1 段階で、クエリ ツリーは次のようになります。In the first stage of query parsing, the query tree looks like this.

ブール クエリの searchMode は any

サポートされるパーサー:シンプルかつ完全な LuceneSupported parsers: Simple and Full Lucene

Azure Cognitive Search では、simple (既定) と full の 2 種類のクエリ言語が使用されます。Azure Cognitive Search exposes two different query languages, simple (default) and full. どちらのクエリ言語を使うかは、検索要求で queryType パラメーターの設定で指定します。その指定に基づいて、クエリ パーサーが演算子と構文を解釈します。By setting the queryType parameter with your search request, you tell the query parser which query language you choose so that it knows how to interpret the operators and syntax. Simple クエリ言語は直感的で安定しており、多くの場合、クライアント側の処理を行わなくてもユーザー入力をそのまま解釈するのに適しています。The Simple query language is intuitive and robust, often suitable to interpret user input as-is without client-side processing. Web 検索エンジンで多く使われているクエリ演算子がサポートされます。It supports query operators familiar from web search engines. Full Lucene クエリ言語は、queryType=full を設定することによって利用できます。より多くの演算子やクエリの種類 (ワイルドカード、あいまい一致、正規表現、フィールド指定検索など) がサポートされることで、既定の Simple クエリ言語が拡張されます。The Full Lucene query language, which you get by setting queryType=full, extends the default Simple query language by adding support for more operators and query types like wildcard, fuzzy, regex, and field-scoped queries. たとえば、Simple クエリ構文で送信された正規表現は、式としてではなくクエリ文字列と解釈されます。For example, a regular expression sent in Simple query syntax would be interpreted as a query string and not an expression. この記事で紹介している要求の例では、Full Lucene クエリ言語を使用しています。The example request in this article uses the Full Lucene query language.

searchMode がパーサーに及ぼす影響Impact of searchMode on the parser

解析方法に作用する検索要求パラメーターとしては、他にも searchMode パラメーターがあります。Another search request parameter that affects parsing is the searchMode parameter. これは、ブール クエリの既定の演算子、つまり any (既定) または all を制御します。It controls the default operator for Boolean queries: any (default) or all.

searchMode=any とした場合 (既定)、spacious と air-condition との間に区切り記号として置かれた空白は OR (||) の働きをするため、前出のサンプル クエリ テキストは次のクエリ テキストに相当します。When searchMode=any, which is the default, the space delimiter between spacious and air-condition is OR (||), making the sample query text equivalent to:

Spacious,||air-condition*+"Ocean view" 

ブール クエリの構造において、明示的な演算子 (+"Ocean view"+ など) の意味ははっきりしています。つまり検索条件との一致は "必須 (must) " です。Explicit operators, such as + in +"Ocean view", are unambiguous in boolean query construction (the term must match). それに比べて、残りの語句 (spacious と air-condition) の解釈はあいまいです。Less obvious is how to interpret the remaining terms: spacious and air-condition. 検索エンジンが探すべきなのは、ocean view spacious air-condition の "すべて" との一致でしょうか。Should the search engine find matches on ocean view and spacious and air-condition? それとも、ocean view に加えて、残りの 2 つの語句のうち、"どちらか一方" のみが含まれていればよいのでしょうか。Or should it find ocean view plus either one of the remaining terms?

既定 (searchMode=any) では、検索エンジンはより広く解釈することを想定します。By default (searchMode=any), the search engine assumes the broader interpretation. どちらか一方のフィールドが一致していればよい (should) の意味、つまり "or" のセマンティクスで解釈されます。Either field should be matched, reflecting "or" semantics. 先ほど例に挙げた、2 つの "should" 演算を含んだクエリ ツリーは既定の動作を示しています。The initial query tree illustrated previously, with the two "should" operations, shows the default.

では、searchMode=all と設定したらどうなるでしょうか。Suppose that we now set searchMode=all. この場合は、空白文字が "and" 演算と解釈されます。In this case, the space is interpreted as an "and" operation. 残りの 2 つの語句が両方とも文書に存在したときに初めて一致と見なされます。Each of the remaining terms must both be present in the document to qualify as a match. 最終的にサンプル クエリは次のように解釈されます。The resulting sample query would be interpreted as follows:

+Spacious,+air-condition*+"Ocean view"

変更後のクエリ ツリーは次のようになり、一致する文書は 3 つすべてのサブクエリの積集合となります。A modified query tree for this query would be as follows, where a matching document is the intersection of all three subqueries:

ブール クエリ searchMode は all

注意

searchMode=all より searchMode=any を選ぶ場合は、代表的なクエリを実行したうえで判断することをお勧めします。Choosing searchMode=any over searchMode=all is a decision best arrived at by running representative queries. 普段から演算子を指定するユーザー (ドキュメント ストアを検索するときなど) は、searchMode=all で得られるブール クエリの構造の方が直感的にわかりやすいかもしれません。Users who are likely to include operators (common when searching document stores) might find results more intuitive if searchMode=all informs boolean query constructs. searchMode と演算子の相互作用について詳しくは、Simple クエリ構文に関するページをご覧ください。For more about the interplay between searchMode and operators, see Simple query syntax.

ステージ 2:字句解析Stage 2: Lexical analysis

クエリ ツリーが構築された後、"単語検索" と "フレーズ検索" のクエリがアナライザーによって加工されます。Lexical analyzers process term queries and phrase queries after the query tree is structured. アナライザーは、パーサーから渡されたテキスト入力を受け取ってそのテキストを加工してから、トークン化した語句をクエリ ツリーに組み入れます。An analyzer accepts the text inputs given to it by the parser, processes the text, and then sends back tokenized terms to be incorporated into the query tree.

最も一般的な字句解析は、特定の言語に固有の規則に従って検索語を変換する "言語分析" です。The most common form of lexical analysis is linguistic analysis which transforms query terms based on rules specific to a given language:

  • 検索語を単語の原形にします。Reducing a query term to the root form of a word
  • ストップワード、つまり検索上の重要性がさほど高くない単語 (英語であれば "the" や "and") を削除します。Removing non-essential words (stopwords, such as "the" or "and" in English)
  • 複合語をその構成要素に分解します。Breaking a composite word into component parts
  • 単語の大文字を小文字に変換します。Lower casing an upper case word

通常はこれらの操作をひととおり適用することで、ユーザーによって入力されたテキストと、インデックスに格納されている語句との相違点が取り除かれます。All of these operations tend to erase differences between the text input provided by the user and the terms stored in the index. こうした操作はテキスト処理の範囲を超えており、言語そのものに対する深い知識が必要となります。Such operations go beyond text processing and require in-depth knowledge of the language itself. この言語知識のレイヤーを追加するために、Azure Cognitive Search は、Lucene と Microsoft から提供されているさまざまな言語アナライザーに対応しています。To add this layer of linguistic awareness, Azure Cognitive Search supports a long list of language analyzers from both Lucene and Microsoft.

注意

解析要件は、実際のシナリオによって大きく異なります。ごく最低限で済む場合もあれば、膨大な作業が必要となる場合もあります。Analysis requirements can range from minimal to elaborate depending on your scenario. 字句解析の難易度は、あらかじめ定義されているいずれかのアナライザーを選択するか、カスタム アナライザーを独自に作成するかによって決まります。You can control complexity of lexical analysis by the selecting one of the predefined analyzers or by creating your own custom analyzer. アナライザーは、検索可能なフィールドにその適用対象が限定されており、フィールド定義の一環として指定されます。Analyzers are scoped to searchable fields and are specified as part of a field definition. これにより、フィールドごとに多様な字句解析を行うことができます。This allows you to vary lexical analysis on a per-field basis. 指定されなかった場合は、"標準" の Lucene アナライザーが使用されます。Unspecified, the standard Lucene analyzer is used.

先ほどの例では、解析前の最初のクエリ ツリーに "Spacious," という語句がありました。大文字の "S" とコンマが含まれています。このコンマは、クエリ パーサーによって検索語の一部と解釈されます (クエリ言語の演算子とは見なされません)。In our example, prior to analysis, the initial query tree has the term "Spacious," with an uppercase "S" and a comma that the query parser interprets as a part of the query term (a comma is not considered a query language operator).

既定のアナライザーは、この語句を加工する際、"ocean view" と "spacious" に含まれている大文字を小文字に変換し、さらにコンマを削除します。When the default analyzer processes the term, it will lowercase "ocean view" and "spacious", and remove the comma character. 変更後のクエリ ツリーは次のようになります。The modified query tree will look as follows:

ブール クエリと解析された語句

アナライザーの動作テストTesting analyzer behaviors

アナライザーの動作は、Analyze API を使ってテストすることができます。The behavior of an analyzer can be tested using the Analyze API. 解析したいテキストを入力すると、指定したアナライザーからどのような語句が生成されるかを確認できます。Provide the text you want to analyze to see what terms given analyzer will generate. たとえば、標準アナライザーで "air-condition" というテキストがどのように加工されるかを確認するには、次のように要求します。For example, to see how the standard analyzer would process the text "air-condition", you can issue the following request:

{
    "text": "air-condition",
    "analyzer": "standard"
}

標準アナライザーは、入力テキストを次の 2 つのトークンに分解します。その際、開始オフセットと終了オフセット (一致部分の強調表示に使用される) やその位置 (フレーズの照合に使用される) など、各種の属性を使ってそれらに注釈を付けます。The standard analyzer breaks the input text into the following two tokens, annotating them with attributes like start and end offsets (used for hit highlighting) as well as their position (used for phrase matching):

{
  "tokens": [
    {
      "token": "air",
      "startOffset": 0,
      "endOffset": 3,
      "position": 0
    },
    {
      "token": "condition",
      "startOffset": 4,
      "endOffset": 13,
      "position": 1
    }
  ]
}

字句解析の例外Exceptions to lexical analysis

字句解析が適用されるのは、語句全体を必要とする種類の検索 (単語検索とフレーズ検索) だけです。Lexical analysis applies only to query types that require complete terms – either a term query or a phrase query. 語句全体を必要としない種類の検索 (プレフィックス検索、ワイルドカード検索、正規表現検索など) やあいまい検索には適用されません。It doesn’t apply to query types with incomplete terms – prefix query, wildcard query, regex query – or to a fuzzy query. 前出の例の air-condition* という語を使ったプレフィックス検索も含め、こうした種類の検索は、解析段階を経ずに直接クエリ ツリーに追加されます。Those query types, including the prefix query with term air-condition* in our example, are added directly to the query tree, bypassing the analysis stage. こうした種類の検索語に対して適用される変換は、大文字から小文字への変換だけです。The only transformation performed on query terms of those types is lowercasing.

ステージ 3:文書検索Stage 3: Document retrieval

ここでいう文書検索とは、一致する語句がインデックスに存在する文書を見つけることです。Document retrieval refers to finding documents with matching terms in the index. この段階は、例を使用するとよくわかります。This stage is understood best through an example. まず、次のような単純なスキーマを使用した hotels というインデックスを考えてみましょう。Let's start with a hotels index having the following simple schema:

{
    "name": "hotels",
    "fields": [
        { "name": "id", "type": "Edm.String", "key": true, "searchable": false },
        { "name": "title", "type": "Edm.String", "searchable": true },
        { "name": "description", "type": "Edm.String", "searchable": true }
    ] 
} 

さらに、このインデックスには、以下の 4 つの文書が追加されているとします。Further assume that this index contains the following four documents:

{
    "value": [
        {
            "id": "1",
            "title": "Hotel Atman",
            "description": "Spacious rooms, ocean view, walking distance to the beach."
        },
        {
            "id": "2",
            "title": "Beach Resort",
            "description": "Located on the north shore of the island of Kauaʻi. Ocean view."
        },
        {
            "id": "3",
            "title": "Playa Hotel",
            "description": "Comfortable, air-conditioned rooms with ocean view."
        },
        {
            "id": "4",
            "title": "Ocean Retreat",
            "description": "Quiet and secluded"
        }
    ]
}

語句のインデックス作成方法How terms are indexed

検索を理解するには、インデックス作成の基本をいくつかを把握しておくと役立ちます。To understand retrieval, it helps to know a few basics about indexing. 保存の単位は転置インデックスで、検索可能なフィールドごとに 1 つ存在します。The unit of storage is an inverted index, one for each searchable field. 転置インデックス内には、全文書から抽出されたすべての語句を並べ替えたリストが存在します。Within an inverted index is a sorted list of all terms from all documents. それぞれの語句は、それが出現する一連の文書に対応付けられています (以下の例を参照)。Each term maps to the list of documents in which it occurs, as evident in the example below.

転置インデックスに含める語句を得るために、検索エンジンは、クエリの加工時と同様の字句解析を文書の内容に対して実行します。To produce the terms in an inverted index, the search engine performs lexical analysis over the content of documents, similar to what happens during query processing:

  1. "テキスト入力" はアナライザーに渡され、小文字への変換や句読点の削除など、アナライザーの構成に応じた処理が行われます。Text inputs are passed to an analyzer, lower-cased, stripped of punctuation, and so forth, depending on the analyzer configuration.
  2. "トークン" は字句解析の出力です。Tokens are the output of lexical analysis.
  3. "用語" はインデックスに追加されます。Terms are added to the index.

検索語の体裁をインデックスに登録されている語句の体裁と合わせるために、通常は検索操作とインデックス作成操作に同じアナライザーが使用されますが、必ずしも同じである必要はありません。It's common, but not required, to use the same analyzers for search and indexing operations so that query terms look more like terms inside the index.

注意

Azure Cognitive Search では、追加の indexAnalyzer および searchAnalyzer フィールド パラメーターを使用して、インデックス作成と検索に別々のアナライザーを指定することができます。Azure Cognitive Search lets you specify different analyzers for indexing and search via additional indexAnalyzer and searchAnalyzer field parameters. 指定しなかった場合、analyzer プロパティで設定されたアナライザーが、インデックス作成と検索の両方に使用されます。If unspecified, the analyzer set with the analyzer property is used for both indexing and searching.

文書サンプルの転置インデックスInverted index for example documents

もう一度先ほどの例を見てみましょう。title フィールドの転置インデックスは、次のようになります。Returning to our example, for the title field, the inverted index looks like this:

期間Term 文書リストDocument list
atmanatman 11
beachbeach 22
hotelhotel 1、31, 3
oceanocean 44
playaplaya 33
resortresort 33
retreatretreat 44

title フィールドの場合、hotel だけが 2 つの文書 (1 と 3) に出現します。In the title field, only hotel shows up in two documents: 1, 3.

description フィールドのインデックスは次のようになっています。For the description field, the index is as follows:

期間Term 文書リストDocument list
airair 33
andand 44
beachbeach 11
conditionedconditioned 33
comfortablecomfortable 33
distancedistance 11
islandisland 22
kauaʻikauaʻi 22
locatedlocated 22
northnorth 22
oceanocean 1, 2, 31, 2, 3
ofof 22
onon 22
quietquiet 44
roomsrooms 1、31, 3
secludedsecluded 44
shoreshore 22
spaciousspacious 11
thethe 1、21, 2
toto 11
viewview 1, 2, 31, 2, 3
walkingwalking 11
withwith 33

インデックスが作成された語句に対する検索語の照合Matching query terms against indexed terms

上記の転置インデックスを踏まえてサンプル クエリに戻り、一致する文書がどのように検索されるかを見ていきましょう。Given the inverted indices above, let’s return to the sample query and see how matching documents are found for our example query. 最終的なクエリ ツリーは、次のようになっていたことを思い出してください。Recall that the final query tree looks like this:

ブール クエリと解析された語句

クエリの実行中、検索可能なフィールドに対して個々の検索が別々に実行されます。During query execution, individual queries are executed against the searchable fields independently.

  • 単語検索 "spacious" と一致する文書は 1 件です (Hotel Atman)。The TermQuery, "spacious", matches document 1 (Hotel Atman).

  • プレフィックス検索 "air-condition*" と一致する文書はありません。The PrefixQuery, "air-condition*", doesn't match any documents.

    これは、場合によっては開発者の混乱を招く動作です。This is a behavior that sometimes confuses developers. "air-conditioned" という語句はこの文書内に存在しますが、既定のアナライザーによって 2 つの単語に分割されています。Although the term air-conditioned exists in the document, it is split into two terms by the default analyzer. プレフィックス検索は、語句全体を含まないため、解析されないことに注意してください。Recall that prefix queries, which contain partial terms, are not analyzed. そのため、転置インデックスで、"air-condition" というプレフィックスを含む語句を検索しても見つかりません。Therefore terms with prefix "air-condition" are looked up in the inverted index and not found.

  • フレーズ検索 "ocean view" では、"ocean" と "view" という 2 つの語句が検索され、元の文書内で両者が近いかどうかがチェックされます。The PhraseQuery, "ocean view", looks up the terms "ocean" and "view" and checks the proximity of terms in the original document. 文書 1、2、3 の description フィールドに、この検索との一致が見つかります。Documents 1, 2 and 3 match this query in the description field. 文書 4 の title には ocean という語が存在しますが、一致とは見なされないことに注意してください。検索対象は "ocean view" というフレーズであって、個々の単語ではありません。Notice document 4 has the term ocean in the title but isn’t considered a match, as we're looking for the "ocean view" phrase rather than individual words.

注意

特定のフィールドを searchFields パラメーター (検索要求の例を参照) で指定しない限り、検索クエリは、Azure Cognitive Search インデックス内の検索可能なすべてのフィールドに対して個別に実行されます。A search query is executed independently against all searchable fields in the Azure Cognitive Search index unless you limit the fields set with the searchFields parameter, as illustrated in the example search request. 選択したフィールドのいずれかで一致する文書が返されます。Documents that match in any of the selected fields are returned.

全体として、この例のクエリの場合、一致する文書は 1、2、3 です。On the whole, for the query in question, the documents that match are 1, 2, 3.

ステージ 4: ポイントの計算Stage 4: Scoring

検索結果セット内のすべての文書には、関連度スコアが割り当てられます。Every document in a search result set is assigned a relevance score. 関連度スコアの機能は、ユーザーからの問い合わせ (検索クエリ) に対して最適解となる文書に対し、相対的に高いランクを与えることです。The function of the relevance score is to rank higher those documents that best answer a user question as expressed by the search query. このスコアは、一致した語句の統計学的な特性に基づいて計算されます。The score is computed based on statistical properties of terms that matched. スコア付けの式の核となるのは TF/IDF (Term Frequency-Inverse Document Frequency) です。At the core of the scoring formula is TF/IDF (term frequency-inverse document frequency). TF/IDF は、出現頻度の低い語句と高い語句を含んだ検索において、出現頻度の低い語句を含んだ結果に、より高いランクを与えます。In queries containing rare and common terms, TF/IDF promotes results containing the rare term. たとえば、Wikipedia の記事をすべて含んだ架空のインデックスでは、the president というクエリに一致した文書のうち、president で一致した文書の方が the で一致した文書よりも関連性が高いと見なされます。For example, in a hypothetical index with all Wikipedia articles, from documents that matched the query the president, documents matching on president are considered more relevant than documents matching on the.

スコア付けの例Scoring example

冒頭のサンプル クエリで見つかった 3 つの文書を思い出してください。Recall the three documents that matched our example query:

search=Spacious, air-condition* +"Ocean view"  
{
  "value": [
    {
      "@search.score": 0.25610128,
      "id": "1",
      "title": "Hotel Atman",
      "description": "Spacious rooms, ocean view, walking distance to the beach."
    },
    {
      "@search.score": 0.08951007,
      "id": "3",
      "title": "Playa Hotel",
      "description": "Comfortable, air-conditioned rooms with ocean view."
    },
    {
      "@search.score": 0.05967338,
      "id": "2",
      "title": "Ocean Resort",
      "description": "Located on a cliff on the north shore of the island of Kauai. Ocean view."
    }
  ]
}

文書 1 は、クエリに対して最も高い関連度で一致しています。なぜなら、spacious という単語と ocean view という必須のフレーズの両方が description フィールドに出現するためです。Document 1 matched the query best because both the term spacious and the required phrase ocean view occur in the description field. その他の 2 つの文書は、ocean view しか一致していません。The next two documents match only the phrase ocean view. しかし文書 2 と文書 3 は、クエリに対して同じように一致しているにもかかわらず、関連度スコアが異なるのはなぜでしょうか。It might be surprising that the relevance score for document 2 and 3 is different even though they matched the query in the same way. これは、スコア付けの式の構成要素が TF/IDF だけではないためです。It's because the scoring formula has more components than just TF/IDF. この場合、文書 3 の方が、description が短いために、少しだけ高いスコアが割り当てられています。In this case, document 3 was assigned a slightly higher score because its description is shorter. フィールドの長さやその他の要因が関連度スコアに与える影響については、Lucene の実際に役立つスコア付けの式に関するページを参照してください。Learn about Lucene's Practical Scoring Formula to understand how field length and other factors can influence the relevance score.

一部の検索の種類 (ワイルドカード、プレフィックス、正規表現) は、文書全体のスコアに対して常に一定のスコアをもたらします。Some query types (wildcard, prefix, regex) always contribute a constant score to the overall document score. これによって、ランクには影響を与えずに、クエリ拡張によって見つかった一致を結果に反映することができます。This allows matches found through query expansion to be included in the results, but without affecting the ranking.

このことが重要である理由を例で説明します。An example illustrates why this matters. ワイルドカード検索 (プレフィックス検索を含む) は、本質的に解釈があいまいです。入力されるのは文字列の一部であり、まったく異なる、膨大な数の語句と一致する可能性があるからです ("tour*" と入力した場合、"tours"、"tourettes"、"tourmaline" などとの一致が検出されます)。Wildcard searches, including prefix searches, are ambiguous by definition because the input is a partial string with potential matches on a very large number of disparate terms (consider an input of "tour*", with matches found on “tours”, “tourettes”, and “tourmaline”). こうした結果の性質上、語句の相対的な重みを適切に推測することができません。Given the nature of these results, there is no way to reasonably infer which terms are more valuable than others. そのため、ワイルドカード検索、プレフィックス検索、正規表現検索では、結果のスコア付けを行う際に、語句の出現頻度が無視されます。For this reason, we ignore term frequencies when scoring results in queries of types wildcard, prefix and regex. 部分的な語句と完全な語句とを含んだ複数の構成要素から成る検索要求では、予期しない一致が偏重されないよう、部分的な入力から得られた結果については、定数スコアを割り当てたうえで反映されます。In a multi-part search request that includes partial and complete terms, results from the partial input are incorporated with a constant score to avoid bias towards potentially unexpected matches.

スコアのチューニングScore tuning

Azure Cognitive Search の関連度スコアは、次の 2 とおりの方法でチューニングできます。There are two ways to tune relevance scores in Azure Cognitive Search:

  1. スコアリング プロファイル: ランク付けされた結果リストにおいて、一連のルールに基づく重みを文書に与えます。Scoring profiles promote documents in the ranked list of results based on a set of rules. このページの例では、title フィールドに一致の見つかった文書の方が、description フィールドに一致の見つかった文書よりも関連性が高いと見なすことができます。In our example, we could consider documents that matched in the title field more relevant than documents that matched in the description field. 加えて、仮にホテルごとの料金フィールドをインデックスに含めた場合、料金の低い方の文書に高い重みを与えることも可能です。Additionally, if our index had a price field for each hotel, we could promote documents with lower price. 詳細については、スコアリング プロファイルを検索インデックスに追加する方法に関するページを参照してください。Learn more how to add Scoring Profiles to a search index.
  2. 項目ブースト (Full Lucene クエリ構文のみで使用可能): クエリ ツリーの任意の構成要素に適用できるブースト演算子 ^ が用意されています。Term boosting (available only in the Full Lucene query syntax) provides a boosting operator ^ that can be applied to any part of the query tree. このページの例では、air-condition* というプレフィックスで検索する代わりに、air-condition^2||air-condition* のように単語検索にブーストを適用することもできます。そうすれば、air-condition で完全一致する語句と、プレフィックスで一致する語句との両方を検索したうえで、完全一致の語句で一致した文書の方に、より高いランクを与えることができます。In our example, instead of searching on the prefix air-condition*, one could search for either the exact term air-condition or the prefix, but documents that match on the exact term are ranked higher by applying boost to the term query: *air-condition^2||air-condition**. 詳細については、項目ブーストに関するセクションを参照してください。Learn more about term boosting.

分散されたインデックスにおけるスコア付けScoring in a distributed index

Azure Cognitive Search のすべてのインデックスは自動的に複数のシャードに分割されます。これにより、Microsoft は、サービスのスケールアップまたはスケールダウンの間に、複数のノードにインデックスをすばやく分散することができます。All indexes in Azure Cognitive Search are automatically split into multiple shards, allowing us to quickly distribute the index among multiple nodes during service scale up or scale down. 検索要求は送信されると、各シャードに対して別々に送られます。When a search request is issued, it’s issued against each shard independently. その後、各シャードから得られた結果がマージされ、スコア順に並べ替えられます (他に並べ替えが定義されていない場合)。The results from each shard are then merged and ordered by score (if no other ordering is defined). 重要なのは、スコア付け機能では、検索語の出現頻度に対する重み付けに、文書頻度 (document frequency) の逆数が使用されますが、その文書頻度の計算対象となる範囲は、すべてのシャード内の全文書ではなく、シャード内の全文書になることを理解することです。It is important to know that the scoring function weights query term frequency against its inverse document frequency in all documents within the shard, not across all shards!

つまり、まったく同じ文書でも、それらが異なるシャードに存在していれば、関連度スコアが異なる "可能性がある" ということです。This means a relevance score could be different for identical documents if they reside on different shards. さいわい、インデックス内の文書数が増えるにつれて語句の分布が平準化され、そのような差異は総じて消失します。Fortunately, such differences tend to disappear as the number of documents in the index grows due to more even term distribution. 文書がどのシャードに配置されるかを推測することは不可能です。It’s not possible to assume on which shard any given document will be placed. しかし文書は、そのキーが変化しなければ、常に同じシャードに割り当てられます。However, assuming a document key doesn't change, it will always be assigned to the same shard.

一般に、順序の不変性が重要となる場合、文書を並べ替えるための特性として、文書のスコアはあまり適していません。In general, document score is not the best attribute for ordering documents if order stability is important. たとえば、まったく同じスコアの文書が 2 つあるとして、同一クエリを繰り返し実行したときに、どちらの文書が上位にランク付けされるかを毎回確実に予測することができないのです。For example, given two documents with an identical score, there is no guarantee which one appears first in subsequent runs of the same query. 文書スコアは、検索結果群における特定の文書の相対的な関連度の高さを測る、おおよその目安としてのみ使用してください。Document score should only give a general sense of document relevance relative to other documents in the results set.

まとめConclusion

インターネット検索エンジンが多くの人々の支持を得たことで、プライベート データに対するフルテキスト検索への期待が高まってきました。The success of internet search engines has raised expectations for full text search over private data. ほぼすべての検索について言えることですが、語句の綴りが間違っていたり不完全であったりしても自分の意図がきちんと反映されるほどの利便性を、私たちは検索エンジンに求めるようになっています。For almost any kind of search experience, we now expect the engine to understand our intent, even when terms are misspelled or incomplete. 実際に指定してもいない同義語やほぼ同等の語句に基づいた検索結果が得られることさえ、当然のように感じてしまうほどです。We might even expect matches based on near equivalent terms or synonyms that we never actually specified.

技術的な観点でいえばフルテキスト検索はきわめて複雑で、洗練された言語分析と検索語の加工 (関連性の高い結果を得るために検索語を抽出、展開、変換する処理) への秩序立ったアプローチとが要求されます。From a technical standpoint, full text search is highly complex, requiring sophisticated linguistic analysis and a systematic approach to processing in ways that distill, expand, and transform query terms to deliver a relevant result. そうした本質的な複雑さもあって、検索結果はさまざまな要因によって左右されます。Given the inherent complexities, there are a lot of factors that can affect the outcome of a query. フルテキスト検索のメカニズムをしっかり理解しておけば、予期しない結果に対処しようとする際に、はっきりとその効果を実感できるでしょう。For this reason, investing the time to understand the mechanics of full text search offers tangible benefits when trying to work through unexpected results.

この記事では、Azure Cognitive Search の観点からフルテキスト検索について詳しく見てきました。This article explored full text search in the context of Azure Cognitive Search. ここで身に付けた知識が、検索時に遭遇しやすい問題の原因や解決策を判断するうえでの一助となればさいわいです。We hope it gives you sufficient background to recognize potential causes and resolutions for addressing common query problems.

次のステップNext steps

関連項目See also

Search Documents REST APISearch Documents REST API

単純なクエリ構文Simple query syntax

Full Lucene クエリ構文Full Lucene query syntax

検索結果の処理方法Handle search results