全文检索

匹配查询

匹配查询是go-to查询,查询首先要知道你要查询那个字段,然后再做其他处理,这就是说match可以处理全文查询和精确值查询。
索引
首先指定了主分片数,然后用_bulk插入。

PUT /my_index
{ "settings": { "number_of_shards": 1 }}
POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "title": "The quick brown fox" }
{ "index": { "_id": 2 }}
{ "title": "The quick brown fox jumps over the lazy dog" }
{ "index": { "_id": 3 }}
{ "title": "The quick brown fox jumps over the quick dog" }
{ "index": { "_id": 4 }}
{ "title": "Brown fox brown dog" }

查询条件

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": "QUICK!"
    }
  }
}

结果

  "hits": {
    "total": 3,
    "max_score": 0.5,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "1",
        "_score": 0.5,
        "_source": {
          "title": "The quick brown fox"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "3",
        "_score": 0.44194174,
        "_source": {
          "title": "The quick brown fox jumps over the quick dog"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "2",
        "_score": 0.3125,
        "_source": {
          "title": "The quick brown fox jumps over the lazy dog"
        }
      }
    ]
  }
}

匹配查询的步骤

  • 检查要查字段的type title字段是全文(analyzed) string字段,即意味着query string也应该被分词。
  • 分析 query string 用的是标准分词器,结果是一个单一条件 quick
  • 找到匹配的文档
  • 计算每个文档的得分 TF IDF 每个字段的长度(越短的字段相关性越高)具体看What is Relevance?

提高精确性

原来的查询方式

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": "BROWN DOG!"
    }
  }
}

新的方式

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": {
        "query": "BROWN DOG!",
        "operator": "and"
      }
    }
  }
}

匹配查询接受operator参数,默认的operator参数是or,可以改成and的形式
你也可以自己指定精确度,使用minimum_should_match参数,表示最少匹配多少百分比。如:

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": {
        "query": "quick brown dog",
        "minimum_should_match": "75%"
      }
    }
  }
}

这个参数是很灵活的,用户输入的条件的项数不同则应用不同的规则,详细请看Minimum Should Match

联合查询

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}

结果

{
  "hits": [
     {
        "_id":      "3",
        "_score":   0.70134366, 
        "_source": {
           "title": "The quick brown fox jumps over the quick dog"
        }
     },
     {
        "_id":      "1",
        "_score":   0.3312608,
        "_source": {
           "title": "The quick brown fox"
        }
     }
  ]
}

在使用should时,查询的结果可以没有should的结果,只是得分比较低。 也是可以控制精确度的,也是使用minimum_should_match

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2 
    }
  }
}

怎样匹配使用bool

下面的两个查询的结果的一样的

{
    "match": { "title": "brown fox"}
}
{
  "bool": {
    "should": [
      { "term": { "title": "brown" }},
      { "term": { "title": "fox"   }}
    ]
  }
}
{
    "match": {
        "title": {
            "query":    "brown fox",
            "operator": "and"
        }
    }
}
{
  "bool": {
    "must": [
      { "term": { "title": "brown" }},
      { "term": { "title": "fox"   }}
    ]
  }
}

主要看一下多字段查询

{
    "match": {
        "title": {
            "query":                "quick brown fox",
            "minimum_should_match": "75%"
        }
    }
}
{
  "bool": {
    "should": [
      { "term": { "title": "brown" }},
      { "term": { "title": "fox"   }},
      { "term": { "title": "quick" }}
    ],
    "minimum_should_match": 2 
  }
}

增强查询子句条款(Boosting Query Clauses)

其目的就是提高某个查询条件的权重,以更多的影响到查询结果的排名。使用boost参数

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {  
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3 
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 
                    }
                }}
            ]
        }
    }
}

结果

  "hits": {
    "total": 4,
    "max_score": 0.783625,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "4",
        "_score": 0.783625,
        "_source": {
          "content": "Full text search with Lucene and Elasticsearch"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "3",
        "_score": 0.40938914,
        "_source": {
          "content": "Full text search with Elasticsearch"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "2",
        "_score": 0.30934063,
        "_source": {
          "content": "Full text search with Lucene"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "1",
        "_score": 0.05462181,
        "_source": {
          "content": "Full text search is great"
        }
      }
    ]
  }
}

NOTE: boost可以大于1也可以小于1,但其效果并不是线性的,只能说boost越大,_score就越高。具体算法就需要专门的书籍了。

控制分词

具体在不同环境中其有不同的默认分词器,详细请看Controlling Analysis

相关性是碎了!(Relevance Is Broken!)

在多字段查询中,我们为什么只给我们创建的索引仅仅一个主分片
多主出现的问题是在我们在一小部分文档中做一个简单的查询,结果,相关性低出现在了相关性高的结果的前面。

  • 相关性 TF/IDF term frequency/inverse document frequency
  • TF 在当前文档中,查询条件出现的次数,出现次数越多,这个文档的相关性就越强。
  • IDF 在所有索引文档中,查询条件在文档中的出现的总和在索引文档中占的一个百分比。出现的越频繁,权重就越轻。
  • 但是,出于性能的原因,es不在所有文档的索引中计算IDF,换句话说,每个分片计算包含在该分片内的本地IDF。导致的问题是同样的条件在不同的分片上其出现的频率是不同的,那么ID/IDF也就不一样了。而我们在进行得分排名时,是一个总的得分。因此就会出现错误的结果。 挽救的方法是在查询时加一个 '?search_type=dfs_query_then_fetch`条件。

NOTE: 建议不要在产品环境下使用。

results matching ""

    No results matching ""