语义查询

由于索引现在配备了 ELSER 嵌入,因此可以更改app.py中的handle_search() 函数来搜索这些嵌入。现在,您将看到如何仅通过 ELSER 进行搜索,稍后将把以前的搜索方法整合回去,创建一个组合解决方案。

要在搜索时使用 ELSER 推断,需要使用text_expansion 查询类型。下面是使用该查询更新后的handle_search() 函数:

@app.post('/')
def handle_search():
    query = request.form.get('query', '')
    filters, parsed_query = extract_filters(query)
    from_ = request.form.get('from_', type=int, default=0)

    results = es.search(
        query={
            'text_expansion': {
                'elser_embedding': {
                    'model_id': '.elser_model_2',
                    'model_text': parsed_query,
                }
            },
        },
        size=5,
        from_=from_,
    )
    return render_template('index.html', results=results['hits']['hits'],
                           query=query, from_=from_,
                           total=results['hits']['total']['value'])

text_expansion 查询接收一个包含要搜索字段名称的键。在该键下,model_id 配置搜索中使用的模型,model_text 定义搜索的内容。请注意,在这种情况下不需要为搜索文本生成嵌入,因为 Elasticsearch 会管理模型并处理该问题。

在上述版本的handle_search() 中,filters 没有使用,聚合也省略了。这些内容可以以同样的方式添加回全文检索解决方案中。下面是更新后的handle_search() 函数,它将text_expansion 查询移至bool.must 部分,在bool.filter 中加入了过滤器,并像以前一样添加了聚合。

@app.post('/')
def handle_search():
    query = request.form.get('query', '')
    filters, parsed_query = extract_filters(query)
    from_ = request.form.get('from_', type=int, default=0)

    results = es.search(
        query={
            'bool': {
                'must': [
                    {
                        'text_expansion': {
                            'elser_embedding': {
                                'model_id': '.elser_model_2',
                                'model_text': parsed_query,
                            }
                        },
                    }
                ],
                **filters,
            }
        },
        aggs={
            'category-agg': {
                'terms': {
                    'field': 'category.keyword',
                }
            },
            'year-agg': {
                'date_histogram': {
                    'field': 'updated_at',
                    'calendar_interval': 'year',
                    'format': 'yyyy',
                },
            },
        },
        size=5,
        from_=from_,
    )
    aggs = {
        'Category': {
            bucket['key']: bucket['doc_count']
            for bucket in results['aggregations']['category-agg']['buckets']
        },
        'Year': {
            bucket['key_as_string']: bucket['doc_count']
            for bucket in results['aggregations']['year-agg']['buckets']
            if bucket['doc_count'] > 0
        },
    }
    return render_template('index.html', results=results['hits']['hits'],
                           query=query, from_=from_,
                           total=results['hits']['total']['value'], aggs=aggs)

花一些时间尝试不同的搜索方式。您会注意到,与密集向量嵌入一样,当索引文档中没有出现确切单词时,ELSER 模型驱动的搜索比全文搜索效果更好。

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用