当前位置: 首页 > 面试题库 >

带有空格的Elasticsearch Nest通配符查询

百里沛
2023-03-14
问题内容

精简版:

我想使用Nest编写一个elasticsearch查询,以获取ContentIndexables已被索引的完整索引项(在我的情况下为自定义类型)。该查询受[somestring] + *(即String.StartsWith())的术语查询的约束,其中[somestring]可能包含空格,也可能不包含空格。

这与CompletionSuggester由于我需要检索完整对象而不是字符串建议而不同。

到目前为止,我已经尝试过:

当我查询没有空格的文本时,将使用下面的代码返回所需的输出。但是,如果我的搜索词包含空格,则不会返回预期结果。

这是我搜索字段的方式:

var searchResults = _client.Search<ContentIndexable>(
            body =>
            body
                .Index(indexName)
                .Query(
                    query =>
                    query.QueryString(
                        qs => qs.
                                  OnFields(f => f.Title, f => f.TextContent)
                                  .Query(searchTerm + "*"))));

这是一个单元测试,演示了如何重现该问题:

indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
        {
            ContentId = Guid.NewGuid(),
            TextContent = "Some description",
            Title = "title"
        });

        indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
        {
            ContentId = Guid.NewGuid(),
            TextContent = "Some description",
            Title = "title that is long"
        });

        indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
        {
            ContentId = Guid.NewGuid(),
            TextContent = "Some description",
            Title = "title that likes"
        });

        indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
        {
            ContentId = Guid.NewGuid(),
            TextContent = "Some description",
            Title = "titlethat"
        });

        var searchResult = indexService.SearchUserItems(testGuid, IndexType.submission, 10, "title");
        Assert.IsNotNull(searchResult);
// this one works
        Assert.AreEqual(4, searchResult.Count());

        var searchResult2 = indexService.SearchUserItems(testGuid, IndexType.submission, 10, "title that");
        Assert.IsNotNull(searchResult2);
// this one does not!!! searchREsult2.Count() evaluates to 0
        Assert.AreEqual(2, searchResult2.Count());

如您所见,然后输入“ title that”,搜索返回为空,而不是我希望返回的两行。

更新: 更多信息:我在我的ContentIndexable类型上创建了一个索引:

public class ContentIndexable : IIndexable
{
    public Guid ContentId { get; html" target="_blank">set; }
    public string Title { get; set; }
    public string TextContent { get; set; }
}

使用此代码:

_client.CreateIndex(
    indexName,
    descriptor =>
    descriptor.AddMapping<ContentIndexable>(
        m => m.Properties(
            p => p.Completion(s => s
                                       .Name(n => n.Title)
                                       .IndexAnalyzer("standard")
                                       .SearchAnalyzer("standard")
                                       .MaxInputLength(30)
                                       .Payloads()
                                       .PreserveSeparators()
                                       .PreservePositionIncrements())
                     .Completion(s => s.Name(n => n.TextContent)
                                          .IndexAnalyzer("standard")
                                          .SearchAnalyzer("standard")
                                          .MaxInputLength(50)
                                          .Payloads()
                                          .PreserveSeparators()
                                          .PreservePositionIncrements())
                 )));

我什至在索引或查询时都试图转义空白,string.Replace(" ", @"\ ")但这没有帮助。

将搜索类型更改为通配符也无济于事:

var searchResults = _client.Search<ContentIndexable>(
            body =>
            body
                .Index(indexName)
                .Query(
                    query => query.Wildcard(qd => qd.OnField(f => f.Title).Value(searchTerm + "*"))));

有人知道我在做什么错吗?

请注意,我的CompletionSuggester版本可以使用空格,但不幸的是只能返回字符串。我需要拿出 完整的物品
才能拿到ContentId。MY CompletionSuggester实施:

public IEnumerable<string> GetAutoCompleteSuggestions(Guid userId, IndexType indexType, int size, string searchTerm)
    {
        string indexName = getIndexName(indexType, userId);

        var result = _client.Search<ContentIndexable>(
            body => body.Index(indexName)
                        .SuggestCompletion("content-suggest" + Guid.NewGuid(),
                                           descriptor => descriptor
                                                             .OnField(t => t.Title)
                                                             .Text(searchTerm)
                                                             .Size(size)));

        if (result.Suggest == null)
        {
            return new List<string>();
        }

        return (from suggest in result.Suggest
                from value in suggest.Value
                from options in value.Options
                select options.Text).Take(size);
    }

我知道我可以接受建议,获得全部价值(这将导致我期望的两个项目),然后使用我的第一种方法进行全期匹配,但这需要对ElasticSearch进行2次单独的调用(一个用于完整的建议者和第二个用于术语查询),但理想情况下,如果可能的话,我希望不进行往返。

提前谢谢了,


问题答案:

这是您如何解决Title现场问题的示例。

将您的映射更改为类似(或使用MultiField,但我找不到同时将字段映射为字符串和完成的选项):

client.CreateIndex(indexName, i => i
    .AddMapping<ContentIndexable>(m => m
        .Properties(
            ps => ps
                .Completion(c => c.Name("title.completion")
                    .IndexAnalyzer("standard")
                    .SearchAnalyzer("standard")
                    .MaxInputLength(30)
                    .Payloads()
                    .PreserveSeparators()
                    .PreservePositionIncrements())
                .String(s => s.Name(x => x.Title).CopyTo("title.completion")))));

更改SuggestCompletion

var result = client.Search<ContentIndexable>(body => body
    .Index(indexName)
    .SuggestCompletion("content-suggest" + Guid.NewGuid(),
        descriptor => descriptor
            .OnField(t => t.Title.Suffix("completion"))
            .Text("title")
            .Size(10)));

QueryString

var searchResponse = client.Search<ContentIndexable>(body => body
    .Index(indexName)
    .Query(query => query
        .QueryString(
            qs => qs
                .OnFields(f => f.Title.Suffix("completion"))
                .Query("title tha" + "*")
                .MinimumShouldMatchPercentage(100))));

该解决方案的问题是事实,我们为Title字段存储了两次数据。这就是为什么我前面提到使用MultiField很好,但是我无法使用NEST

希望这可以帮助。



 类似资料:
  • 我正在编写一个Python程序,该程序使用Selenium导航到高级搜索页面上的搜索框中并在搜索框中输入信息。本网站使用 Javascript,每次加载网站时,每个搜索框的 ID 和名称都会略有变化,但类名保持不变。类名经常被重用,所以我的目标是使用然后通过该列表编制索引。 例如,一个框的类名是 ,但我不能使用它,因为 selenium 认为它是一个复合类名并抛出一个错误。如果我只使用它的一部分,

  • 问题内容: 我尝试将正则表达式匹配为app.yaml中的目录名的尝试不起作用: 尽管此官方规范说正则表达式语法受支持。有办法使这项工作吗? 即应该匹配静态文件。 琐事 我使用Google App Engine服务Go Webapp。 我想最大程度地延长浏览器缓存的寿命,最大程度地减少请求数,并仍提供我的css / js / png的新版本,并且我相信修改文件名是实现此目的的最佳实践。另外,由于添加

  • 在我的NestJS项目中,我有这个TypeORM查询: 现在我只想返回名称中包含的用户。在SQL中,这将是一个查询。 在https://github.com/typeorm/typeorm/blob/master/docs/find-options.md中,没有关于通配符查询的信息。 如何执行like查询类型ORM给出了一个解决方案: 但是,我无法使用和,后者在使用而不是时可用。 对于如何使用Ty

  • 我试图使用JSoup从超文本标记语言文档中选择一些文本。 我感兴趣的超文本标记语言是表单的一部分: 我对获取任何

  • 我需要构造正则表达式来验证文本,它可以包含空格和连字符,除了连字符之外没有数字和特殊字符。文本应以字母开头。没有以空格和连字符开头和结尾。单词之间应允许使用单个空格。 ASDF-A ADF-AAD A-A-A A DDD-A 示例 AD-AA-A ADF-ad-DD-A AAA

  • 我正在尝试从Java文本文件中读取一行。我得到一个异常。 这是文本文件中的行: 我需要用“#”拆分,这部分起作用了。当我试图访问位置1处的元素时,Java抛出异常。我想这是因为名字和姓氏之间有空格,因为当我显示的是“Chiquita”,而不是“Chiquita Sanford”。 当第一个数组索引中有多个单词时,Java对拆分是否有一些限制。