NEST - MultiMatch 在术语为空时搜索所有文档 - Elasticsearch 6.4

NEST - MultiMatch search all documents when term is empty - Elasticsearch 6.4

我正在尝试使用 NEST 和多匹配选项进行查询,但结果并不像预期的那样。

我提交了一个应该与多个领域进行比较的术语。但是,如果您不设置搜索词,则必须返回所有文档。

我看到可以使用“*.*”这样的关键字,但是没有用。 有什么建议吗?

var searchResponse = client.Search<DocumentElasticModel>(s => s
              .Size(pageSize)
              .Skip(currentPageIndex * pageSize)
              .Sort(ss => ss
                .Descending(SortSpecialField.Score)
              )
              .Source(sf => sf
                .Includes(i => i
                    .Fields(
                        returnedFields
                    )
                )
              )
              .Query(q => q
                .Nested(c => c
                    .Name("named_query")
                    .Boost(1.1)
                    .InnerHits(i => i.Explain())
                    .Path(p => p.PerguntasRespostas)
                    .Query(nq => nq
                        .MultiMatch(m => m
                            .Fields(f => filterFields) 
-----------------------WHEN THE 'SEARCH' IS EMPTY, SHOULD FIND ALL -----------------
                            .Query(string.IsNullOrEmpty(search) ? string.Empty : search)
                        )
                    )
                    .IgnoreUnmapped()
                )
              )

NEST 默认支持此功能,其概念称为 Conditionless queries。你可以

private static void Main()
{
    var defaultIndex = "documents";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool, new InMemoryConnection())
        .DefaultIndex(defaultIndex)
        .DisableDirectStreaming()
        .PrettyJson()
        .OnRequestCompleted(callDetails =>
        {
            if (callDetails.RequestBodyInBytes != null)
            {
                Console.WriteLine(
                    $"{callDetails.HttpMethod} {callDetails.Uri} \n" +
                    $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");
            }
            else
            {
                Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
            }

            Console.WriteLine();

            if (callDetails.ResponseBodyInBytes != null)
            {
                Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                         $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                         $"{new string('-', 30)}\n");
            }
            else
            {
                Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                         $"{new string('-', 30)}\n");
            }
        });

    var client = new ElasticClient(settings);

    var pageSize = 20;
    var currentPageIndex = 0;  
    string search = "foo";


    var searchResponse = client.Search<DocumentElasticModel>(s => s
        .Size(pageSize)
        .Skip(currentPageIndex * pageSize)
        .Sort(ss => ss
            .Descending(SortSpecialField.Score)
        )
        .Source(sf => sf
            .Includes(i => i
                .Fields(f => f.TopLevelMessage)
            )
        )
        .Query(q => q
            .Nested(c => c
                .Name("named_query")
                .Boost(1.1)
                .InnerHits(i => i.Explain())
                .Path(p => p.PerguntasRespostas)
                .Query(nq => nq
                    .MultiMatch(m => m
                        .Fields(f => f
                            .Field(ff => ff.PerguntasRespostas.First().Message)
                        ) 
                        .Query(search)
                    )
                )
                .IgnoreUnmapped()
            )
        )
    );
}


public class DocumentElasticModel 
{
    public string TopLevelMessage { get; set; }

    public IEnumerable<PerguntasRespostas> PerguntasRespostas {get;set;}
}

public class PerguntasRespostas
{
    public string Message { get; set; }  
}

这将发送以下查询

POST http://localhost:9200/documents/documentelasticmodel/_search
{
  "from": 0,
  "size": 20,
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ],
  "_source": {
    "includes": [
      "topLevelMessage"
    ]
  },
  "query": {
    "nested": {
      "_name": "named_query",
      "boost": 1.1,
      "query": {
        "multi_match": {
          "query": "foo",
          "fields": [
            "perguntasRespostas.message"
          ]
        }
      },
      "path": "perguntasRespostas",
      "inner_hits": {
        "explain": true
      },
      "ignore_unmapped": true
    }
  }
}

现在,如果您将 search 更改为 string.Emptynull,您将得到

POST http://localhost:9200/documents/documentelasticmodel/_search
{
  "from": 0,
  "size": 20,
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ],
  "_source": {
    "includes": [
      "topLevelMessage"
    ]
  }
}

请求中没有明确的 "query",这与 match_all 查询相同。

如果您想覆盖 NEST 中的无条件查询功能,您可以将查询标记为 .Verbatim(),NEST 将按原样发送

var searchResponse = client.Search<DocumentElasticModel>(s => s
    .Size(pageSize)
    .Skip(currentPageIndex * pageSize)
    .Sort(ss => ss
        .Descending(SortSpecialField.Score)
    )
    .Source(sf => sf
        .Includes(i => i
            .Fields(f => f.TopLevelMessage)
        )
    )
    .Query(q => q
        .Nested(c => c
            .Verbatim() // <-- mark the nested query
            .Name("named_query")          
            .Boost(1.1)
            .InnerHits(i => i.Explain())
            .Path(p => p.PerguntasRespostas)
            .Query(nq => nq
                .MultiMatch(m => m
                    .Verbatim() // <-- mark the inner query
                    .Fields(f => f
                        .Field(ff => ff.PerguntasRespostas.First().Message)
                    ) 
                    .Query(search)
                )
            )
            .IgnoreUnmapped()
        )
    )
);

哪个发送

POST http://localhost:9200/documents/documentelasticmodel/_search
{
  "from": 0,
  "size": 20,
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ],
  "_source": {
    "includes": [
      "topLevelMessage"
    ]
  },
  "query": {
    "nested": {
      "_name": "named_query",
      "boost": 1.1,
      "query": {
        "multi_match": {
          "fields": [
            "perguntasRespostas.message"
          ]
        }
      },
      "path": "perguntasRespostas",
      "inner_hits": {
        "explain": true
      },
      "ignore_unmapped": true
    }
  }
}

您需要检查这是否是 Elasticsearch 接受的有效查询。