elasticsearch,query-optimization,wildcard,Java,elasticsearch,Query Optimization,Wildcard" /> elasticsearch,query-optimization,wildcard,Java,elasticsearch,Query Optimization,Wildcard" />

ElasticSearch查询优化-Java API

ElasticSearch查询优化-Java API,java,elasticsearch,query-optimization,wildcard,Java,elasticsearch,Query Optimization,Wildcard,我是ES的新手,正在搜索100k数据的记录集。 这是我的映射和设置JSON,我用它为数据编制了索引: setings.json { "index": { "analysis": { "tokenizer": { "ngram_tokenizer": { "type": "ngram", "min_gram": 3,

我是ES的新手,正在搜索100k数据的记录集。 这是我的映射和设置JSON,我用它为数据编制了索引:

setings.json

{
    "index": {
        "analysis": {
            "tokenizer": {
                "ngram_tokenizer": {
                    "type": "ngram",
                    "min_gram": 3,
                    "max_gram": 10
                }
            },
            "analyzer": {
                "ngram_tokenizer_analyzer": {
                    "type": "custom",
                    "tokenizer": "ngram_tokenizer"
                }
            }
        }
    }
}
mappings.json

{
    "product": {
        "properties": {
            "name": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "description": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "vendorModelNumber": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "brand": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "specifications": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "upc": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "storeSkuId": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            },
            "modelNumber": {
                "type": "string",
                "analyzer": "ngram_tokenizer_analyzer",
                "store": true
            }
        }
    }
}
我需要根据所提到的所有字段按一定的优先级查询文档。这是我搜索所有记录的查询

BoolQueryBuilder query = QueryBuilders.boolQuery();
int boost = 7;

for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("name", "*" + str.toLowerCase() + "*").boost(boost));
}
boost--;
for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("description", "*" + str.toLowerCase() + "*").boost(boost));
}
boost--;
for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("modelNumber", "*" + str.toLowerCase() + "*").boost(boost));
}
boost--;
for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("vendorModelNumber", "*" + str.toLowerCase() + "*").boost(boost));
}
boost--;
for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("storeSkuId", "*" + str.toLowerCase() + "*").boost(boost));
}
boost--;
for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("upc", "*" + str.toLowerCase() + "*").boost(boost));
}
boost--;
for (String str : dataSplit) {
    query.should(QueryBuilders.wildcardQuery("brand", "*" + str.toLowerCase() + "*").boost(boost));
}
client.prepareSearch(index).setQuery(query).setSize(200).setExplain(true).execute().actionGet();
这个查询确实可以帮助我搜索数据,而且效果很好,但我的问题是,因为我使用通配符查询,所以需要花费很多时间。 请有人帮我优化这个查询,或者指导我找到最适合我搜索的查询?
蒂亚

首先,让我先回答一个简单的问题:处理区分大小写。如果定义自定义分析器,则可以添加不同的过滤器,这些过滤器在标记器处理输入后应用于每个标记

{
"index": {
    "analysis": {
        "tokenizer": {
            "ngram_tokenizer": {
                "type": "ngram",
                "min_gram": 3,
                "max_gram": 10
            }
        },
        "analyzer": {
            "ngram_tokenizer_analyzer": {
                "type": "custom",
                "tokenizer": "ngram_tokenizer",
                "filter": [
                    "lowercase",
                    ...
                ]
            }
        }
    }
}
如您所见,存在一个现有的小写过滤器,它将简单地将所有标记转换为小写。我强烈建议您参考。有很多这样的令牌过滤器

现在是更复杂的部分:NGram标记器。同样,为了更深入地理解,您可能需要阅读。但提到您的问题,您的标记器基本上会创建长度为3到10的术语。这意味着文本

I am an example TEXT.
基本上会创建很多代币。仅举几个例子:

尺码3:I a、am、am、…、TEX、EXT 尺寸4:我是,我是,我是,…,特克斯,文本。 尺码10:我是前任。。。 你明白了。小写标记过滤器现在将这些标记小写

匹配和术语查询之间的区别:将分析匹配查询,而不分析术语查询。事实上,这意味着您的匹配查询可以匹配多个术语。例:你和考试成绩相符

事实上,这将匹配3个术语:exa、xam和exam

这对比赛的分数有影响。比赛越多,分数越高。在某些情况下,这是需要的,在其他情况下不是

不会分析学期查询,这意味着考试将匹配,但当然只有一个学期考试。然而,由于它没有被分析,它也不是小写的,这意味着你必须自己在代码中这样做。考试永远不会匹配,因为如果使用小写标记过滤器,索引中没有带大写字母的术语

不确定您的用例。但我有一种感觉,你可以甚至想要使用查询这个词。但请注意,索引中没有大于10的项。因为你的ngram标记器就是这么做的

/编辑:


关于匹配查询,以及您可能希望使用术语的原因,值得指出的是:一些匹配查询(如Simple)也将匹配示例中的mple。

为什么首先使用通配符查询?使用具有3+的ngram标记器,正常匹配查询应使用长度超过2个字符的输入。或者ngram标记器的原因是什么?旁注;使用定义的此分析器,您的查询将区分大小写。可能是有意的,但很不寻常。谢谢@Slomo你是对的。我不应该在ngram中使用通配符。我可以不区分大小写吗?对于ngram,我应该使用术语查询或匹配进行查询,哪种方式更为理想?如果这不是一个合理的问题,那么很抱歉:详细解释请参见tnx a lot@Slomo。将对我的代码进行优化,并对文档进行检查:因此,假设我需要在多个字段上搜索多个值,使用匹配查询的bool将是一个不错的选择,对吗?@DivyaMenon您可以。或者,您也可以使用where,您还应该能够对字段进行加权。也许一个具有预期结果的具体查询示例有助于回答您的问题。