MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

ElasticSearch 匹配查询的多样化应用场景

2023-05-051.9k 阅读

ElasticSearch 匹配查询基础概述

ElasticSearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎,其匹配查询功能极为强大,能满足各种复杂的数据检索需求。匹配查询主要用于在指定字段中查找与给定文本相匹配的文档。

在 ElasticSearch 中,匹配查询的核心是理解文本分析的过程。当我们进行匹配查询时,输入的文本会经过分析器的处理。分析器会将文本拆分成一个个的词项(token),然后 ElasticSearch 根据这些词项在倒排索引中进行查找。

例如,对于一个简单的文本 “ElasticSearch is a powerful search engine”,分析器可能会将其拆分成 “elasticsearch”、“is”、“a”、“powerful”、“search”、“engine” 等词项。然后 ElasticSearch 在相关字段的倒排索引中查找包含这些词项的文档。

基本匹配查询语法

在 ElasticSearch 中,使用 match 查询来执行基本的匹配操作。以下是一个简单的示例,假设我们有一个名为 products 的索引,其中包含 title 字段,我们要查找标题中包含 “smartphone” 的产品:

{
    "query": {
        "match": {
            "title": "smartphone"
        }
    }
}

上述查询会对 title 字段进行匹配,查找包含 “smartphone” 词项的文档。需要注意的是,这里的查询会根据 title 字段所配置的分析器来处理查询文本。

多字段匹配查询

在实际应用中,我们常常需要在多个字段中进行匹配。例如,在一个电商产品索引中,我们可能希望在 titledescriptionbrand 字段中同时查找与某个关键词相关的产品。可以使用 multi_match 查询来实现这一需求:

{
    "query": {
        "multi_match": {
            "query": "apple",
            "fields": ["title", "description", "brand"]
        }
    }
}

上述查询会在 titledescriptionbrand 这三个字段中查找包含 “apple” 词项的文档。multi_match 查询提供了多种类型的匹配策略,如 best_fields(默认策略,查找在多个字段中最佳匹配的文档)、most_fields(查找在多个字段中出现词项最多的文档)和 cross_fields(将多个字段视为一个大字段进行匹配)。

全文搜索场景下的匹配查询

网页搜索引擎应用

在网页搜索引擎的构建中,ElasticSearch 的匹配查询发挥着关键作用。假设我们要构建一个简单的网页搜索引擎,索引包含网页的标题、正文和 URL 等信息。

首先,我们创建索引映射:

PUT /web_pages
{
    "mappings": {
        "properties": {
            "title": {
                "type": "text"
            },
            "body": {
                "type": "text"
            },
            "url": {
                "type": "keyword"
            }
        }
    }
}

然后,我们向索引中添加一些网页文档:

POST /web_pages/_doc
{
    "title": "ElasticSearch Tutorial",
    "body": "This is a tutorial about ElasticSearch and its powerful search capabilities.",
    "url": "https://example.com/elasticsearch-tutorial"
}

POST /web_pages/_doc
{
    "title": "Search Engines Comparison",
    "body": "Compare different search engines like Google, Bing and ElasticSearch based search engines.",
    "url": "https://example.com/search-engines-comparison"
}

当用户在搜索框中输入关键词,比如 “ElasticSearch” 时,我们可以使用以下查询:

{
    "query": {
        "multi_match": {
            "query": "ElasticSearch",
            "fields": ["title", "body"]
        }
    }
}

这样就可以查找出标题或正文中包含 “ElasticSearch” 的网页文档。在实际应用中,还可以结合评分机制,对匹配结果进行排序,将相关性更高的网页排在前面。例如,可以根据词项在文档中的出现频率、文档的权威性等因素来计算评分。

文档检索系统

在企业文档检索系统中,通常需要对大量的文档进行快速检索。假设企业有各种类型的文档,如 Word 文档、PDF 文档等,并且已经将这些文档的文本内容提取出来并存储到 ElasticSearch 索引中。索引可能包含文档的标题、作者、内容等字段。

创建索引映射:

PUT /enterprise_docs
{
    "mappings": {
        "properties": {
            "title": {
                "type": "text"
            },
            "author": {
                "type": "text"
            },
            "content": {
                "type": "text"
            }
        }
    }
}

添加文档示例:

POST /enterprise_docs/_doc
{
    "title": "Project Plan for New Product",
    "author": "John Doe",
    "content": "The project plan outlines the steps and timelines for the development of the new product."
}

POST /enterprise_docs/_doc
{
    "title": "Market Analysis Report",
    "author": "Jane Smith",
    "content": "This report analyzes the market trends and competitors for our product."
}

当员工需要查找与 “new product” 相关的文档时,可以使用以下查询:

{
    "query": {
        "multi_match": {
            "query": "new product",
            "fields": ["title", "content"]
        }
    }
}

此外,还可以通过添加过滤条件来进一步缩小搜索范围。比如,只查找特定作者的文档:

{
    "query": {
        "bool": {
            "must": {
                "multi_match": {
                    "query": "new product",
                    "fields": ["title", "content"]
                }
            },
            "filter": {
                "term": {
                    "author": "John Doe"
                }
            }
        }
    }
}

这样就可以查找出 John Doe 撰写的与 “new product” 相关的文档。

电商搜索场景下的匹配查询

产品搜索

在电商平台中,产品搜索是核心功能之一。假设电商平台有一个 products 索引,包含产品的标题、描述、品牌、价格等字段。

创建索引映射:

PUT /products
{
    "mappings": {
        "properties": {
            "title": {
                "type": "text"
            },
            "description": {
                "type": "text"
            },
            "brand": {
                "type": "text"
            },
            "price": {
                "type": "float"
            }
        }
    }
}

添加产品文档示例:

POST /products/_doc
{
    "title": "iPhone 14 Pro",
    "description": "The latest flagship smartphone from Apple with advanced camera and performance features.",
    "brand": "Apple",
    "price": 999.99
}

POST /products/_doc
{
    "title": "Samsung Galaxy S23 Ultra",
    "description": "A high - end Android smartphone with a large display and powerful camera capabilities.",
    "brand": "Samsung",
    "price": 1199.99
}

当用户在搜索框中输入 “smartphone” 时,可以使用以下查询来查找相关产品:

{
    "query": {
        "multi_match": {
            "query": "smartphone",
            "fields": ["title", "description"]
        }
    }
}

为了提供更好的搜索体验,电商平台通常还会支持价格范围过滤、品牌过滤等功能。例如,用户希望查找价格在 500 到 1000 之间的智能手机,可以使用以下查询:

{
    "query": {
        "bool": {
            "must": {
                "multi_match": {
                    "query": "smartphone",
                    "fields": ["title", "description"]
                }
            },
            "filter": {
                "range": {
                    "price": {
                        "gte": 500,
                        "lte": 1000
                    }
                }
            }
        }
    }
}

如果用户还希望只查看某个品牌的产品,比如 “Apple”,可以进一步添加品牌过滤:

{
    "query": {
        "bool": {
            "must": {
                "multi_match": {
                    "query": "smartphone",
                    "fields": ["title", "description"]
                }
            },
            "filter": [
                {
                    "range": {
                        "price": {
                            "gte": 500,
                            "lte": 1000
                        }
                    }
                },
                {
                    "term": {
                        "brand": "Apple"
                    }
                }
            ]
        }
    }
}

商品推荐关联搜索

电商平台的商品推荐功能也可以借助 ElasticSearch 的匹配查询来实现。假设平台记录了用户的浏览历史和购买历史,并将这些信息存储在 ElasticSearch 索引中。索引可能包含用户 ID、浏览或购买的产品 ID、时间等字段。

创建索引映射:

PUT /user_activity
{
    "mappings": {
        "properties": {
            "user_id": {
                "type": "keyword"
            },
            "product_id": {
                "type": "keyword"
            },
            "activity_type": {
                "type": "keyword"
            },
            "timestamp": {
                "type": "date"
            }
        }
    }
}

添加用户活动文档示例:

POST /user_activity/_doc
{
    "user_id": "user123",
    "product_id": "prod456",
    "activity_type": "purchase",
    "timestamp": "2023 - 10 - 01T12:00:00Z"
}

POST /user_activity/_doc
{
    "user_id": "user123",
    "product_id": "prod789",
    "activity_type": "view",
    "timestamp": "2023 - 10 - 02T14:30:00Z"
}

当为用户推荐商品时,可以先查找与该用户有相似购买或浏览行为的其他用户,然后推荐这些用户购买或浏览过的产品。例如,查找与 “user123” 有相似行为的用户:

{
    "query": {
        "bool": {
            "must_not": {
                "term": {
                    "user_id": "user123"
                }
            },
            "filter": {
                "terms": {
                    "product_id": [
                        "prod456",
                        "prod789"
                    ]
                }
            }
        }
    }
}

得到相似用户后,再查找这些用户购买或浏览过但 “user123” 未接触过的产品,就可以作为推荐商品。这一过程中,匹配查询用于在用户活动索引中查找相关记录,为商品推荐提供数据支持。

日志分析场景下的匹配查询

系统日志检索

在系统运维中,日志分析是重要的环节。假设我们有一个系统日志索引 system_logs,包含日志级别(如 INFO、WARN、ERROR)、时间戳、日志消息等字段。

创建索引映射:

PUT /system_logs
{
    "mappings": {
        "properties": {
            "log_level": {
                "type": "keyword"
            },
            "timestamp": {
                "type": "date"
            },
            "message": {
                "type": "text"
            }
        }
    }
}

添加日志文档示例:

POST /system_logs/_doc
{
    "log_level": "INFO",
    "timestamp": "2023 - 11 - 01T08:00:00Z",
    "message": "System started successfully."
}

POST /system_logs/_doc
{
    "log_level": "ERROR",
    "timestamp": "2023 - 11 - 02T15:30:00Z",
    "message": "Database connection error: Connection refused."
}

当运维人员需要查找特定时间范围内的错误日志时,可以使用以下查询:

{
    "query": {
        "bool": {
            "must": {
                "term": {
                    "log_level": "ERROR"
                }
            },
            "filter": {
                "range": {
                    "timestamp": {
                        "gte": "2023 - 11 - 01T00:00:00Z",
                        "lte": "2023 - 11 - 02T23:59:59Z"
                    }
                }
            }
        }
    }
}

如果还想在错误日志消息中查找包含 “database” 关键词的记录,可以进一步修改查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {
                        "log_level": "ERROR"
                    }
                },
                {
                    "match": {
                        "message": "database"
                    }
                }
            ],
            "filter": {
                "range": {
                    "timestamp": {
                        "gte": "2023 - 11 - 01T00:00:00Z",
                        "lte": "2023 - 11 - 02T23:59:59Z"
                    }
                }
            }
        }
    }
}

应用程序日志分析

对于应用程序日志,除了基本的日志级别和消息外,可能还包含模块名称、请求 ID 等信息。假设应用程序日志索引 app_logs 具有以下映射:

PUT /app_logs
{
    "mappings": {
        "properties": {
            "log_level": {
                "type": "keyword"
            },
            "module": {
                "type": "keyword"
            },
            "request_id": {
                "type": "keyword"
            },
            "message": {
                "type": "text"
            }
        }
    }
}

添加日志文档示例:

POST /app_logs/_doc
{
    "log_level": "WARN",
    "module": "payment",
    "request_id": "req123",
    "message": "Payment processing took longer than expected."
}

POST /app_logs/_doc
{
    "log_level": "ERROR",
    "module": "user_auth",
    "request_id": "req456",
    "message": "User authentication failed."
}

如果要查找某个模块(如 “payment”)的所有警告日志,可以使用以下查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {
                        "log_level": "WARN"
                    }
                },
                {
                    "term": {
                        "module": "payment"
                    }
                }
            ]
        }
    }
}

若要跟踪某个特定请求 ID(如 “req123”)的所有日志,可以这样查询:

{
    "query": {
        "term": {
            "request_id": "req123"
        }
    }
}

通过这些匹配查询,可以快速定位应用程序中的问题,提高故障排查效率。

匹配查询的高级应用场景

模糊匹配

在某些情况下,用户可能输入的关键词不太准确,但我们仍然希望能找到相关的文档。ElasticSearch 支持模糊匹配。例如,在一个地名索引中,用户可能将 “New York” 误输入为 “Ne Yrk”。

假设我们有一个 places 索引,包含 name 字段:

PUT /places
{
    "mappings": {
        "properties": {
            "name": {
                "type": "text"
            }
        }
    }
}

添加文档:

POST /places/_doc
{
    "name": "New York"
}

POST /places/_doc
{
    "name": "Los Angeles"
}

使用模糊匹配查询:

{
    "query": {
        "match": {
            "name": {
                "query": "Ne Yrk",
                "fuzziness": "AUTO"
            }
        }
    }
}

这里的 fuzziness 设置为 “AUTO”,ElasticSearch 会根据查询词的长度自动确定允许的编辑距离。编辑距离表示将一个词转换为另一个词所需的最少单字符编辑操作(插入、删除、替换)次数。通过模糊匹配,可以提高搜索的容错性,为用户提供更友好的搜索体验。

短语匹配

短语匹配用于查找文档中包含与给定短语完全相同顺序的词项的内容。例如,在一个新闻文章索引中,我们希望查找包含特定短语 “data privacy regulations” 的文章。

假设新闻文章索引 news_articles 有以下映射:

PUT /news_articles
{
    "mappings": {
        "properties": {
            "title": {
                "type": "text"
            },
            "content": {
                "type": "text"
            }
        }
    }
}

添加文章文档:

POST /news_articles/_doc
{
    "title": "New Data Privacy Regulations in Europe",
    "content": "The new data privacy regulations in Europe are set to impact many companies."
}

POST /news_articles/_doc
{
    "title": "Data Security vs Privacy",
    "content": "While data security is important, data privacy regulations also need to be considered."
}

使用短语匹配查询:

{
    "query": {
        "match_phrase": {
            "content": "data privacy regulations"
        }
    }
}

上述查询只会返回内容中包含 “data privacy regulations” 这个完整短语的文档,而不会返回只是包含这三个词但顺序不同的文档。短语匹配在需要精确匹配特定词序的场景中非常有用,如法律条文检索、特定术语查找等。

跨语言匹配

随着全球化的发展,很多应用需要支持多语言搜索。ElasticSearch 可以通过配置不同的分析器来实现跨语言匹配。例如,假设我们有一个产品目录,包含英文和法文的产品描述。

创建索引映射并配置多语言分析器:

PUT /multilingual_products
{
    "mappings": {
        "properties": {
            "description_en": {
                "type": "text",
                "analyzer": "english"
            },
            "description_fr": {
                "type": "text",
                "analyzer": "french"
            }
        }
    }
}

添加产品文档:

POST /multilingual_products/_doc
{
    "description_en": "A beautiful dress",
    "description_fr": "Une belle robe"
}

POST /multilingual_products/_doc
{
    "description_en": "A comfortable shoes",
    "description_fr": "Des chaussures confortables"
}

如果用户用英文搜索 “beautiful dress”,可以这样查询:

{
    "query": {
        "match": {
            "description_en": "beautiful dress"
        }
    }
}

如果用户用法文搜索 “belle robe”,则:

{
    "query": {
        "match": {
            "description_fr": "belle robe"
        }
    }
}

通过这种方式,ElasticSearch 能够有效地支持跨语言的匹配查询,满足不同语言用户的搜索需求。在实际应用中,还可以结合语言检测功能,自动识别用户输入的语言并选择相应的字段进行查询,进一步提升用户体验。

地理位置匹配

在一些应用场景中,如本地服务搜索、物流跟踪等,需要根据地理位置进行匹配查询。ElasticSearch 支持地理位置数据类型和相关查询。假设我们有一个本地商家索引 local_businesses,包含商家名称、地址和地理位置信息。

创建索引映射:

PUT /local_businesses
{
    "mappings": {
        "properties": {
            "name": {
                "type": "text"
            },
            "address": {
                "type": "text"
            },
            "location": {
                "type": "geo_point"
            }
        }
    }
}

添加商家文档示例:

POST /local_businesses/_doc
{
    "name": "ABC Coffee Shop",
    "address": "123 Main St",
    "location": {
        "lat": 37.7749,
        "lon": -122.4194
    }
}

POST /local_businesses/_doc
{
    "name": "XYZ Bookstore",
    "address": "456 Elm St",
    "location": {
        "lat": 37.7755,
        "lon": -122.4188
    }
}

如果用户想查找距离某个坐标(如 37.7750, -122.4190)一定范围内的商家,可以使用以下查询:

{
    "query": {
        "bool": {
            "filter": {
                "geo_distance": {
                    "distance": "1km",
                    "location": {
                        "lat": 37.7750,
                        "lon": -122.4190
                    }
                }
            }
        }
    }
}

上述查询会返回距离指定坐标 1 公里范围内的商家。还可以结合其他文本匹配条件,如查找距离指定位置一定范围内且商家名称包含 “coffee” 的商家:

{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "name": "coffee"
                }
            },
            "filter": {
                "geo_distance": {
                    "distance": "1km",
                    "location": {
                        "lat": 37.7750,
                        "lon": -122.4190
                    }
                }
            }
        }
    }
}

通过地理位置匹配查询,能够为用户提供基于位置的精准搜索结果,满足各种与位置相关的业务需求。

结合机器学习的匹配查询

随着机器学习技术的发展,ElasticSearch 也可以与机器学习相结合,提升匹配查询的效果。例如,可以利用机器学习模型来预测用户的搜索意图,从而优化查询结果。

假设我们有一个电商搜索场景,通过收集大量的用户搜索日志和相应的点击行为数据,可以训练一个机器学习模型(如深度学习模型)来预测用户输入查询词后的潜在需求。当用户输入一个查询词,如 “laptop”,模型可能预测出用户更感兴趣的是游戏本还是轻薄本。

然后,在 ElasticSearch 查询中,可以根据模型的预测结果调整查询条件。如果模型预测用户更感兴趣的是游戏本,可以在查询中增加对 “gaming laptop” 相关特征的权重。例如:

{
    "query": {
        "function_score": {
            "query": {
                "multi_match": {
                    "query": "laptop",
                    "fields": ["title", "description"]
                }
            },
            "functions": [
                {
                    "filter": {
                        "match": {
                            "description": "gaming laptop"
                        }
                    },
                    "weight": 2
                }
            ]
        }
    }
}

上述查询中,通过 function_score 对包含 “gaming laptop” 的文档增加了权重,使得这些文档在搜索结果中更靠前。通过结合机器学习,能够更好地理解用户意图,提供更符合用户需求的匹配查询结果,提升搜索体验和业务转化率。

在实际应用中,还可以使用机器学习进行异常检测,在日志分析场景中,如果发现某些日志消息模式与正常模式不同,可以标记为异常。然后在匹配查询中,可以专门查找这些异常日志,以便及时发现和解决系统问题。例如,通过训练一个异常检测模型,对日志消息进行编码,然后根据编码的异常程度来调整查询结果,优先展示可能存在问题的日志。

综上所述,ElasticSearch 的匹配查询在各种多样化的应用场景中都有着强大的功能和广泛的应用。通过灵活运用不同类型的匹配查询以及结合其他功能和技术,能够满足不同领域、不同业务需求的复杂数据检索和分析任务。无论是全文搜索、电商搜索、日志分析,还是高级的模糊匹配、跨语言匹配等场景,ElasticSearch 都能提供有效的解决方案,助力企业和开发者构建高效、智能的数据检索和分析系统。