Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elasticsearch搜索-全文查询(第二章) #3

Open
BlackHole1 opened this issue Dec 27, 2018 · 0 comments
Open

Elasticsearch搜索-全文查询(第二章) #3

BlackHole1 opened this issue Dec 27, 2018 · 0 comments

Comments

@BlackHole1
Copy link
Contributor

BlackHole1 commented Dec 27, 2018

Elasticsearch搜索-全文查询(第二章)

上一篇:Elasticsearch搜索-基本搜索(第一章)

全文查询

上节基本都是以 term 进行搜索,但其实 Elasticsearch 提供了很多搜索方法,本章就是介绍 Elasticsearch 有哪些搜索方法、分别起的作用。

本章对 common_terms queryquery_string querysimple_query_string query 没有解释说明,因为使用起来较少,而且解释起来较为麻烦。如果想了解,可以参考网上的文章。这里就不在阐述了。

match query

我们先使用 term 进行一次查询:

GET books/_search
{
  "_source": ["title", "author"],
  "query": {
    "term": {
      "title": "java编程"
    }
  }
}

你会发现,其结果为空(但是数据库里是有这个数据的),如图:

Imgur

这是因为 term 是匹配分词后的词项来进行查询的。比如刚刚我们查的 java编程 ,在 Elasticsearch 进行分词时,会把 java编程 分为:java编程 。导致匹配不起来。

用代码诠释的话就是:

const keyword = 'java编程';
const data = ['java', '编程'];
const result = data.includes(keyword);
console.log(result) //=> false

现在我们把 term 换成 match 来尝试下:

GET books/_search
{
  "_source": ["title", "author"],
  "query": {
    "match": {
      "title": "java编程"
    }
  }
}

结果如图:

Imgur

可以发现,已经有结果了,但是为什么会有两个呢?

原因是因为 match 会对你的关键字进行分词,然后去匹配文档分词后的结果,只要文档里的词项能匹配关键字分词后的任何一个,都会返回到结果里。

代码诠释:

const data = ['java', '编程', '思想']; // 分词后的文档里的数据
const keywords = ['java', '编程', '思想']; // 分词后的关键字

const result = (() => {
  for (let x = 0; x < data.length; x++) {
    const dataItem = data[x];
    for (let y = 0; y < keywords.length; y++) {
      const keywordItem = keywords[y];
      if (dataItem === keywordItem) {
        return true;
      }
    }
  }
  return false;
})()

如果我只想让它返回一个呢,并且只能用 match 来做,可以么?

是可以的,match 提供了一个属性:operator。可以用这个来帮助完成这个需求:

GET books/_search
{
  "_source": ["title", "author"],
  "query": {
    "match": {
      "title": {
        "query": "java编程",
        "operator": "and"
      }
    }
  }
}

最终的结果如图:

Imgur

原理是因为 operator 属性的值为 and,这样的话,就告诉 Elasticsearch 我要让我的关键字都能和文档里的词项匹配上。有一个没匹配上,我都不要。

如果 operator 属性的值为 or,那结果就和之前是一样的了。

match_phrase query

你可以把这个方法理解为自带了 operator 属性的值为 andmatch

这个方法有两个限制条件,只有都满足,才会在结果中显示出:

  • 分词后的所有词项都在该字段中,相当于 operator: "and"
  • 顺序要一致

顺序一致指的是什么呢?

假设你使用 match 来匹配: 编程java,那么结果还是和上面一样。所以如果你需要要求顺序一致性,那么你就可以使用 match_phrase 来做。

如果使用 编程java 来搜索:

Imgur

如果使用 java编程

Imgur

match_phrase_prefix query

这个方法和 match_phrase 方法类似,不过这个方法可以可以把最后一个词项作为前缀进行匹配,想象一下:用户在搜索栏中搜索 辣鸡UZ,然后下面列表中出现了 辣鸡UZI

首先 match_phrase_prefix 会先分词为: 辣鸡,然后找了一个文档,再然后匹配 辣鸡 后面的字符串是否以 UZ 开头的。这个时候文档满足条件,就返回出结果。可以假想后面一直有一个(.*)的通配符,如:辣鸡UZ(.*)

知道原理了,我们现在写一个查询语句:

GET books/_search
{
  "_source": ["title", "author"],
  "query": {
    "match_phrase_prefix": {
      "title": "java编"
    }
  }
}

结果如图:

Imgur

multi_match query

multi_matchmatch 的升级方法,可以用来搜索多个字段。

比如我不想只在 title 里搜索 java编程,我还想在 description 里进行搜索。那应该怎么做呢?

Elasticsearch 已经提供了 multi_match 专门用来处理这件事情:

GET books/_search
{
  "_source": ["title", "description"],
  "query": {
    "multi_match": {
      "query": "java编程",
      "fields": ["title", "description"]
    }
  }
}

最终结果如图:

Imgur

并且 multi_match 还支持通配符。上面的查询语句,可以写成:

GET books/_search
{
  "_source": ["title", "description"],
  "query": {
    "multi_match": {
      "query": "java编程",
      "fields": ["title", "*tion"]
    }
  }
}

下一篇:Elasticsearch搜索-词项查询(第三章)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant