PHP中使用ElasticSearch

本文介绍了ES中组合条件查询的强大功能,通过bool语法可拼接复杂条件。还介绍了常用组合查询关键词,如filter、must等。以ES6.5为测试环境,循序渐进展示了添加和搜索功能,包括新建index、定义type、插入数据、取数据等,最后贴出基于Laravel的完整测试代码。

时间:2021-07-16 09:31:12

在es中,使用组合条件查询是其作为搜索引擎检索数据的一个强大之处,在前几篇中,简单演示了es的查询语法,但基本的增删改查功能并不能很好的满足复杂的查询场景,比如说我们期望像mysql那样做到拼接复杂的条件进行查询该如何做呢?es中有一种语法叫bool,通过在bool里面拼接es特定的语法可以做到大部分场景下复杂条件的拼接查询,也叫复合查询

首先简单介绍es中常用的组合查询用到的关键词,

filter:过滤,不参与打分
must:如果有多个条件,这些条件都必须满足 and与
should:如果有多个条件,满足一个或多个即可 or或
must_not:和must相反,必须都不满足条件才可以匹配到 !非

1

2

3

4

5

6

7

{

    "bool": {

        "must": [],--必须满足的条件--and 

        "should": [],--可以满足也可以不满足的条件--or 

        "must_not": []--不能满足的条件--not

    }

}

发生 描述
must
该条款(查询)必须出现在匹配的文件,并将有助于得分。

filter
子句(查询)必须出现在匹配的文档中。然而不像 must查询的分数将被忽略。Filter子句在过滤器上下文中执行,这意味着评分被忽略,子句被考虑用于高速缓存。

should
子句(查询)应该出现在匹配的文档中。如果 bool查询位于查询上下文中并且具有mustor filter子句,则bool即使没有should查询匹配,文档也将匹配该查询 。在这种情况下,这些条款仅用于影响分数。如果bool查询是过滤器上下文 或者两者都不存在,must或者filter至少有一个should查询必须与文档相匹配才能与bool查询匹配。这种行为可以通过设置minimum_should_match参数来显式控制 。

must_not
子句(查询)不能出现在匹配的文档中。子句在过滤器上下文中执行,意味着评分被忽略,子句被考虑用于高速缓存。因为计分被忽略,0所有文件的分数被返回。

网上很多关于ES的例子都过时了,版本很久,这篇文章的测试环境是ES6.5

通过composer 安装

1

composer require 'elasticsearch/elasticsearch'

在代码中引入

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

require 'vendor/autoload.php';

use Elasticsearch\ClientBuilder;

// 配置

$client = ClientBuilder::create()->setHosts(['172.16.55.53'])->build();

// 配置

$client = ClientBuilder::create()->setHosts([

    [

        'host' => 'xxx',

        'port' => '9200',

        'scheme' => 'http',

        'user' => 'xxx',

        'pass' => 'xxxx'

    ],

])->build();

下面循序渐进完成一个简单的添加和搜索的功能。

首先要新建一个 index:

index 对应关系型数据(以下简称MySQL)里面的数据库,而不是对应MySQL里面的索引,这点要清楚

1

2

3

4

5

6

7

8

9

10

$params = [

    'index' => 'myindex', #index的名字不能是大写和下划线开头

    'body' => [

        'settings' => [

            'number_of_shards' => 2,

            'number_of_replicas' => 0

        ]

    ]

];

$client->indices()->create($params);

在MySQL里面,光有了数据库还不行,还需要建立表,ES也是一样的,ES中的type对应MySQL里面的表。

注意:ES6以前,一个index有多个type,就像MySQL中一个数据库有多个表一样自然,但是ES6以后,每个index只允许一个type,在往以后的版本中很可能会取消type。

type不是单独定义的,而是和字段一起定义

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

$params = [

    'index' => 'myindex',

    'type' => 'mytype',

    'body' => [

        'mytype' => [

            '_source' => [

                'enabled' => true

            ],

            'properties' => [

                'id' => [

                    'type' => 'integer'

                ],

                'first_name' => [

                    'type' => 'text',

                    'analyzer' => 'ik_max_word'

                ],

                'last_name' => [

                    'type' => 'text',

                    'analyzer' => 'ik_max_word'

                ],

                'age' => [

                    'type' => 'integer'

                ]

            ]

        ]

    ]

];

$client->indices()->putMapping($params);

在定义字段的时候,可以看出每个字段可以定义单独的类型,在first_name中还自定义了 分词器 ik,

这个分词器是一个插件,需要单独安装的,参考另一篇文章:ElasticSearch基本尝试

现在 数据库和表都有了,可以往里面插入数据了

概念:这里的 数据 在ES中叫 文档

1

2

3

4

5

6

7

8

9

10

11

$params = [

    'index' => 'myindex',

    'type' => 'mytype',

    //'id' => 1, #可以手动指定id,也可以不指定随机生成

    'body' => [

        'first_name' => '张',

        'last_name' => '三',

        'age' => 35

    ]

];

$client->index($params);

多插入一点数据,然后来看看怎么把数据取出来:

通过id取出单条数据:

插曲:如果你之前添加文档的时候没有传入id,ES会随机生成一个id,这个时候怎么通过id查?id是多少都不知道啊。

所以这个插入一个简单的搜索,最简单的,一个搜索条件都不要,返回所有index下所有文档:

1

$data $client->search();

现在可以去找一找id了,不过你会发现id可能长这样:zU65WWgBVD80YaV8iVMk,不要惊讶,这是ES随机生成的。

现在可以通过id查找指定文档了:

1

2

3

4

5

6

$params = [

    'index' => 'myindex',

    'type' => 'mytype',

    'id' =>'zU65WWgBVD80YaV8iVMk'

];

$data $client->get($params);

最后一个稍微麻烦点的功能:

注意:这个例子我不打算在此详细解释,看不懂没关系,这篇文章主要的目的是基本用法,并没有涉及到ES的精髓地方,

ES精髓的地方就在于搜索,后面的文章我会继续深入分析

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

$query = [

    'query' => [

        'bool' => [

            'must' => [

                'match' => [

                    'first_name' => '张',

                ]

            ],

            'filter' => [

                'range' => [

                    'age' => ['gt' => 76]

                ]

            ]

        ]

    ]

];

$params = [

    'index' => 'myindex',

//  'index' => 'm*', #index 和 type 是可以模糊匹配的,甚至这两个参数都是可选的

    'type' => 'mytype',

    '_source' => ['first_name','age'], // 请求指定的字段

    'body' => array_merge([

        'from' => 0,

        'size' => 5

    ],$query)

];

$data $this->EsClient->search($params);

上面的是一个简单的使用流程,但是不够完整,只讲了添加文档,没有说怎么删除文档,

下面我贴出完整的测试代码,基于Laravel环境,当然环境只影响运行,不影响理解,包含基本的常用操作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值