Elasticsearch学習ノート上級編(十一)-マルチフィールド検索(下)

11008 ワード

前のブログを引き継ぐhttps://segmentfault.com/a/11...

4、most_fieldsクエリー


most_fieldsはフィールドを中心としており、最も一致するフィールドをクエリーします.ユーザーにアドレスを検索させるものがあるとします.次の2つのドキュメントがあります.
PUT /test_index/_create/1
{
    "street":   "5 Poland Street",
    "city":     "Poland",
    "country":  "United W1V",
    "postcode": "W1V 3DG"
}

PUT /test_index/_create/2
{
    "street":   "5 Poland Street W1V",
    "city":     "London",
    "country":  "United Kingdom",
    "postcode": "3DG"
}

most_の使用fieldsによるクエリー:
GET /test_index/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "street": "Poland Street W1V"
          }
        },
        {
          "match": {
            "city": "Poland Street W1V"
          }
        },
        {
          "match": {
            "country": "Poland Street W1V"
          }
        },
        {
          "match": {
            "postcode": "Poland Street W1V"
          }
        }
      ]
    }
  }
}

各フィールドに対してクエリー文字列を繰り返すとすぐに冗長になりmulti_matchは以下のように簡略化される.
GET /test_index/_search
{
  "query": {
    "multi_match": {
      "query": "Poland Street W1V",
      "type": "most_fields", 
      "fields": ["street", "city", "country", "postcode"]
    }
  }
}

結果:
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 2.3835402,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 2.3835402,
        "_source" : {
          "street" : "5 Poland Street",
          "city" : "Poland",
          "country" : "United W1V",
          "postcode" : "W1V 3DG"
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.99938464,
        "_source" : {
          "street" : "5 Poland Street W1V",
          "city" : "London",
          "country" : "United Kingdom",
          "postcode" : "3DG"
        }
      }
    ]
  }
}

best_を使うとfields、doc 2はdoc 1の前にあります
GET /test_index/_search
{
  "query": {
    "multi_match": {
      "query": "Poland Street W1V",
      "type": "best_fields", 
      "fields": ["street", "city", "country", "postcode"]
    }
  }
}

結果:
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.99938464,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.99938464,
        "_source" : {
          "street" : "5 Poland Street W1V",
          "city" : "London",
          "country" : "United Kingdom",
          "postcode" : "3DG"
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6931472,
        "_source" : {
          "street" : "5 Poland Street",
          "city" : "Poland",
          "country" : "United W1V",
          "postcode" : "W1V 3DG"
        }
      }
    ]
  }
}

most_の使用フィールドに存在する問題


(1)すべてのフィールドにまたがる最も一致する単語を見つけるのではなく、任意の単語に一致する多数のフィールドを見つけるように設計されています(2)operatorまたはminimum_を使用できません.should_matchパラメータは,低相関結果による長尾効果を低減するために用いられる(3)各フィールドの語条頻度が異なり,互いに干渉し,最終的に劣る並べ替え結果を得る.

5、全フィールドクエリーcopy_を使用するtoパラメータ


most_と言いましたFieldsの問題は、次はこの問題を解決します.この問題を解決する最初の方法はcopyを使うことです.toパラメータ.copyを使ってto複数のfieldを1つのfieldに組み合わせて、次のインデックスを作成します.
DELETE /test_index
PUT /test_index
{
  "mappings": {
    "properties": {
      "street": {
        "type": "text",
        "copy_to": "full_address"
      },
      "city": {
        "type": "text",
        "copy_to": "full_address"
      },
      "country": {
        "type": "text",
        "copy_to": "full_address"
      },
      "postcode": {
        "type": "text",
        "copy_to": "full_address"
      },
      "full_address": {
        "type": "text"
      }
    }
  }
}

前のデータを挿入:
PUT /test_index/_create/1
{
    "street":   "5 Poland Street",
    "city":     "Poland",
    "country":  "United W1V",
    "postcode": "W1V 3DG"
}

PUT /test_index/_create/2
{
    "street":   "5 Poland Street W1V",
    "city":     "London",
    "country":  "United Kingdom",
    "postcode": "3DG"
}

クエリー:
GET /test_index/_search
{
  "query": {
    "match": {
      "full_address": "Poland Street W1V"
    }
  }
}

結果:
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.68370587,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.68370587,
        "_source" : {
          "street" : "5 Poland Street",
          "city" : "Poland",
          "country" : "United W1V",
          "postcode" : "W1V 3DG"
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.5469647,
        "_source" : {
          "street" : "5 Poland Street W1V",
          "city" : "London",
          "country" : "United Kingdom",
          "postcode" : "3DG"
        }
      }
    ]
  }
}

フィールドfullになることがわかりますaddressの後、most_を解決できます.fieldsの問題です.

5、cross_fieldsクエリー


解決するfieldsの問題の2つ目の方法はcross_を使用することですfieldsクエリー.ドキュメントをインデックスする前に使用できる場合はallまたはcopyを事前に定義します.toなら、大丈夫です.しかし、Elasticsearchはcross_を使用する検索期間のソリューションも提供しています.fieldsクエリー.cross_fieldsは単語を中心とした方法を採用し,best_とfieldsおよびmost_fieldsが採用するフィールド中心の方法には大きな違いがある.すべてのフィールドを大きなフィールドと見なし、任意のフィールドで各単語を検索します.フィールド中心と見出し語中心の違いを説明します.

フィールド中心


クエリーを使用:
GET /test_index/_validate/query?explain
{
  "query": {
    "multi_match": {
      "query": "Poland Street W1V",
      "type": "best_fields",
      "fields": ["street", "city", "country", "postcode"]
    }
  }
}

取得:
{
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "valid" : true,
  "explanations" : [
    {
      "index" : "test_index",
      "valid" : true,
      "explanation" : "((postcode:poland postcode:street postcode:w1v) | (country:poland country:street country:w1v) | (city:poland city:street city:w1v) | (street:poland street:street street:w1v))"
    }
  ]
}

(postcode:poland postcode:street postcode:w 1 v)|(country:poland country:street country:w 1 v)|(city:poland city:street city:w 1 v)|(street:poland street:street:w 1 v))これがルールです.operatorをandに設定すると(((+postcode:poland+postcode:street+postcode:w 1 v)|(+country:poland+country:street+country:w 1 v)|(+city:poland+city:street+city:w 1 v)|(+street:poland+street:street:street+street:w 1 v))4つの単語が同じフィールドに表示される必要があることを示します.

単語中心


クエリーによる
GET /test_index/_validate/query?explain
{
  "query": {
    "multi_match": {
      "query": "Poland Street W1V",
      "type": "cross_fields", 
      "operator": "and", 
      "fields": ["street", "city", "country", "postcode"]
    }
  }
}

取得:
{
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "valid" : true,
  "explanations" : [
    {
      "index" : "test_index",
      "valid" : true,
      "explanation" : "+blended(terms:[postcode:poland, country:poland, city:poland, street:poland]) +blended(terms:[postcode:street, country:street, city:street, street:street]) +blended(terms:[postcode:w1v, country:w1v, city:w1v, street:w1v])"
    }
  ]
}

+blended(terms:[postcode:poland,country:poland,city:poland,street:poland])+blended(terms:[postcode:street,country:street,city:street,street:street])+blended(terms:[postcode:w 1 v,country:w 1 v,city:w 1 v,street:w 1 v])これがルールです.言い換えれば、すべての語は任意のフィールドに表示されなければならない.cross_fieldsタイプでは、まずクエリー文字列を解析して単語リストを取得し、任意のフィールドで各単語を検索します.フィールドのバックグラウンドドキュメント頻度をブレンドすることで、単語頻度の問題を解決します.それで完璧な結末になったmost_fieldsの問題.cross_の使用fieldsはcopy_よりtoは、クエリ中に個別フィールドを重み付けすることができる.例:
GET /test_index/_search
{
  "query": {
    "multi_match": {
      "query": "Poland Street W1V",
      "type": "cross_fields", 
      "fields": ["street^2", "city", "country", "postcode"]
    }
  }
}

これによりstreetフィールドのboostは2であり、他のフィールドは1である.