Elasticsearch正确的逃生方式,?在所有情况下都不起作用

时间:2018-01-18 18:10:57

标签: c# elasticsearch elasticsearch-5

我正在尝试使用空格进行搜索以在弹性搜索中正常工作,但在使其行为与在另一个字段上的行为方式相同时会遇到很多麻烦。

我有两个字段NameAddresses.First().Line1,我希望能够在搜索中搜索和保留空格。例如,搜索Bob Smi*会返回Bob Smith,但不仅仅是Bob

这适用于我的“名称”字段,方法是使用?替换空格进行查询字符串搜索。我也在做一个通配符,所以我的最终查询是*bob?smi*

然而,当我尝试也按行1搜索时,我没有得到任何结果。例如。 *4800*会返回包含{1}}等第1行的记录,但当我使用4800 Street进行相同的转换以获取4800 street时,我得不到任何结果。

以下是我的查询

*4800?street*

不会返回任何结果。

为什么{ "from": 0, "size": 50, "query": { "bool": { "must": [ { "query_string": { "query": "*4800?Street*", "fields": [ "name", "addresses.line1" ] } } ] } } } 会返回名称为*bob?smi*的结果,但Bob Smith不会返回包含订单项*4800?street*的结果?

以下是如何在索引中设置两个字段:

4800 street

弹性映射:

.Text(smd => smd.Name(c => c.Name).Analyzer(ElasticIndexCreator.SortAnalyzer).Fielddata())

.Nested<Address>(nomd => nomd.Name(p => p.PrimaryAddress).Properties(MapAddressProperties))

//from MapAddressProperties()

.Text(smd2 => smd2.Name(x => x.Line1).Analyzer(ElasticIndexCreator.SortAnalyzer).Fielddata())

还有其他更好的方法来逃避弹性搜索查询字符串中的空格吗?我还尝试了"name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } "addresses": { "line1": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, } \\(在C#评估为\\\\)而不是\\无效。

2 个答案:

答案 0 :(得分:0)

尝试在 addresses.line1.keyword参数中使用keyword(即,尝试为addresses.line1定义的fields多字段) term-level wildcard query

{
    "query": {
        "wildcard": {
            "addresses.line1.keyword": {
                "wildcard": "*4800 street*"
            }
        }
    }
}

Elasticsearch documentation on full-text wildcard searches,如果您搜索addresses.line1(其类型为text,以便应用全文搜索规则),则会针对从字段中分析的每个字词执行搜索,即一次针对4800再次针对street,其中任何一个都不会与您的*4800?street*通配符匹配。 addresses.line1.keyword多字段包含原始4800 street值,并且应使用术语级通配符查询与您的查询模式匹配。

顺便说一下,一个次要的:映射类型定义本身对addresses字段来说似乎不完整。你说是:

"addresses": {
    "line1": {
        "type": "text",
        "fields": {
            "keyword": {
                "type": "keyword",
                "ignore_above": 256
            }
        }
    },
}

但恕我直言,它应该是:

"addresses": {
    "properties": {
        "line1": {
            "type": "text",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        },
    }
}

答案 1 :(得分:0)

经过大量时间的实验,终于找到了正确的设置。对我有用的配置如下:

  1. 在列
  2. 中使用带有字段数据的文本
  3. 使用带有通配符占位符的QueryString进行搜索,将空格替换为?,例如输入bob smith,使用*bob?smith*
  4. 查询弹性
  5. 对子对象使用嵌套查询。奇怪的是,addresses.line1会在搜索说4800时返回数据,但在尝试*4800?street*时则不会。使用嵌套查询可以使其正常运行。
  6. 据我所知,不得不使用现场数据是非常耗费内存的,并且必须使用通配符是非常耗时的,所以这可能不是最佳解决方案,但它是我发现的唯一解决方案。如果还有另一种更好的方法,请赐教。

    使用Nest在C#中进行查询:

    var query = Query<Student>.QueryString(qs => qs
                    .Fields(f => f
                    .Field(c => c.Name)
                    //.Field(c => c.PrimaryAddress.Line1) //this doesn't work
                    )
                    .Query(testCase.Term)
                );
    
    query |= Query<Student>.Nested(n => n
            .Path(p => p.Addresses)
                .Query(q => q
                    .QueryString(qs => qs
                            .Fields(f => f.Field(c => c.Addresses.First().Line1))
                            .Query(testCase.Term)
                        )
                )
            );
    

    示例映射:

    .Map<Student>(s => s.Properties(p => p
        .Text(t => t.Name(z => z.Name).Fielddata())
        .Nested<StudentAddress>(n => n
            .Name(ap => ap.Addresses)
            .Properties(ap => ap.Text(t => t.Name(z => z.Line1).Fielddata())
        )
    ))