在 Elasticsearch 中,经常会遇到类似数据的不同索引具有不同字段名称的情况。 例如,一个索引可能使用字段名 level 来表示日志级别,而另一个索引可能使用 log_level 来达到相同目的。 出现这种不一致的原因有多种,例如不同的团队使用不同的命名约定、不断发展的数据模型或集成来自不同来源的数据。
跨两个索引搜索日志级别
要在 loglevel_test1 和 loglevel_test2 索引中搜索日志级别为 "info" 的所有文档,考虑到不同的字段名称,你可以按如下方式构建查询:
bash
1. PUT loglevel_test1/_doc/1
2. {
3. "level":"This is a very useful info in test1"
4. }
6. DELETE loglevel_test2
7. PUT loglevel_test2/_doc/1
8. {
9. "log_level":"This is a very useful info in test2"
10. }
13. GET loglevel_test1,loglevel_test2/_search?filter_path=**.hits
14. {
15. "query": {
16. "bool": {
17. "should": [
18. {
19. "term": {
20. "level": "info"
21. }
22. },
23. {
24. "term": {
25. "log_level": "info"
26. }
27. }
28. ],
29. "minimum_should_match": 1
30. }
31. }
32. }
此查询检查 loglevel_test1 中的 level 字段和 loglevel_test2 中的 log_level 字段的值 "info"。 在 bool 查询中使用 should 子句可以灵活地匹配任一条件。 minimum_should_match 参数确保文档匹配时至少有一个条件为真,从而从两个索引返回所有相关文档。
上述查询的结果为:
json
1. {
2. "hits": {
3. "hits": [
4. {
5. "_index": "loglevel_test2",
6. "_id": "1",
7. "_score": 0.2876821,
8. "_source": {
9. "log_level": "This is a very useful info in test2"
10. }
11. },
12. {
13. "_index": "loglevel_test1",
14. "_id": "1",
15. "_score": 0.12343237,
16. "_source": {
17. "level": "This is a very useful info in test1"
18. }
19. }
20. ]
21. }
22. }
使用 alias 来完成
我们可以参考文章 "Elasticsearch : alias 数据类型"。在索引中,我们可以为 loglevel_test2 定义如下的 alias:
bash
1. PUT loglevel_test2/_mapping
2. {
3. "properties": {
4. "level": {
5. "type": "alias",
6. "path": "log_level"
7. }
8. }
9. }
这样 level 也就是 log_level 的别名。我们再次使用如下的命令来进行搜索:
bash
1. GET loglevel_test1,loglevel_test2/_search?filter_path=**.hits
2. {
3. "query": {
4. "match": {
5. "level": "info"
6. }
7. }
8. }
上面搜索的结果是:
json
1. {
2. "hits": {
3. "hits": [
4. {
5. "_index": "loglevel_test1",
6. "_id": "1",
7. "_score": 0.2876821,
8. "_source": {
9. "level": "This is a very useful info in test1"
10. }
11. },
12. {
13. "_index": "loglevel_test2",
14. "_id": "1",
15. "_score": 0.2876821,
16. "_source": {
17. "log_level": "This is a very useful info in test2"
18. }
19. }
20. ]
21. }
22. }
当然上面的搜索索引名称也有一大串。在使用的时候并不方便。我们可以再次使用如下的技巧来进行精简:
bash
1. GET loglevel_test*/_search?filter_path=**.hits
2. {
3. "query": {
4. "match": {
5. "level": "info"
6. }
7. }
8. }