NEST复合查询必须全部满足

时间:2017-07-20 09:48:02

标签: c# elasticsearch nest

var availableToField = Infer.Field<Project>(f => f.Availablity.AvailableTo);
var availableFromField = Infer.Field<Project>(f => f.Availablity.AvailableFrom);
var nameField = Infer.Field<Project>(f => f.Contact.Name);

var active_date_to = new DateRangeQuery(){
            Name = "toDate",
            Boost = 1.1,
            Field = "availablity.availableTo",
            GreaterThan = DateTime.Now,
            TimeZone = "+01:00",
            Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
        };
var active_date_from = new DateRangeQuery(){
            Name = "from",
            Boost = 1.1,
            Field = "availablity.availableFrom",
            LessThanOrEqualTo = DateTime.Now,
            TimeZone = "+01:00",
            Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
        };

public ISearchResult<Project> Search(SearchCriteria criteria)
        {var ret = _client.Search<Project>(s =>
                s.Query(q =>


                        active_date_from &&
                        active_date_to &&
                        q.Match(d => d.Query(criteria.FreeText))
                        ).From(criteria.CurrentPage).Size(criteria.Take)
                        .From(criteria.CurrentPage)
                        .Take(criteria.Take)

            );
result.Total = ret.Total;
            result.Page = criteria.CurrentPage;
            result.PerPage = criteria.Take;
            result.Results = ret.Documents;
            return result;
}

我想要做的是获得与freetext相匹配的结果,但也正在考虑价格范围。 不知怎的,虽然我得到的是一个无效的NEST响应构建来自POST上的不成功的低级别调用...因此是一个空查询。 没有编译错误。

有没有人知道我哪里可能出错或者我错过了什么?

我尝试的另一件事是

var mustClauses = new List<QueryContainer>();
            mustClauses.Add(active_date_from);
            mustClauses.Add(active_date_to);            
            mustClauses.Add(new TermQuery
            {
                Field = "contact.name",
                Value = criteria.FreeText
            });

            var searchRequest = new SearchRequest<Project>()
            {
                Size = 10,
                From = 0,
                Query = new BoolQuery
                {
                    Must = mustClauses

                }

            };

            var ret = _client.Search<Project>(searchRequest);

            result.Total = ret.Total;
            result.Page = criteria.CurrentPage;
            result.PerPage = criteria.Take;
            result.Results = ret.Documents;

这让我得到了相同的结果..(读:无)

有什么东西我不见了?

编辑: 但是......这个:

var ret = _client.Search<Project>(s => s.Query(q => q.Match(m => m.Field(f => f.DisplayName).Query(criteria.FreeText))));

给了我我想要的东西(当然没有验证日期,只看一个字段)

1 个答案:

答案 0 :(得分:0)

在第一个示例中,match查询缺少查询所需的field属性。由于NEST的conditionless query behaviour,查询未被序列化为请求的一部分。但是,这两个日期范围查询是序列化的。

这是一个简单的示例,您可能会发现有用的信息可以帮助您找到正确的查询

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "projects";
    var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection())
        .DefaultIndex(defaultIndex )
        .PrettyJson()
        .DisableDirectStreaming()
        .OnRequestCompleted(response =>
            {
                if (response.RequestBodyInBytes != null)
                {
                    Console.WriteLine(
                        $"{response.HttpMethod} {response.Uri} \n" +
                        $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}");
                }
                else
                {
                    Console.WriteLine($"{response.HttpMethod} {response.Uri}");
                }

                Console.WriteLine();

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

    var client = new ElasticClient(connectionSettings);

    var availableToField = Infer.Field<Project>(f => f.Availablity.AvailableTo);
    var availableFromField = Infer.Field<Project>(f => f.Availablity.AvailableFrom);
    var nameField = Infer.Field<Project>(f => f.Contact.Name);

    var active_date_to = new DateRangeQuery
    {
        Name = "toDate",
        Boost = 1.1,
        Field = availableToField,
        GreaterThan = DateTime.Now,
        TimeZone = "+01:00",
        Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
    };
    var active_date_from = new DateRangeQuery
    {
        Name = "from",
        Boost = 1.1,
        Field = availableFromField,
        LessThanOrEqualTo = DateTime.Now,
        TimeZone = "+01:00",
        Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
    };

    var ret = client.Search<Project>(s => s
        .Query(q =>
            active_date_from &&
            active_date_to && q
            .Match(d => d
                .Query("free text")
            )
        )
        .From(0)
        .Size(10)
    );
}

public class Project
{
    public Availibility Availablity { get; set; }
    public Contact Contact { get; set; }
}

public class Contact
{
    public string Name { get; set; }
}

public class Availibility
{
    public DateTime AvailableFrom { get; set; }
    public DateTime AvailableTo { get; set; }
}

您当前的查询生成

POST http://localhost:9200/projects/project/_search?pretty=true 
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "availablity.availableFrom": {
              "lte": "2017-07-21T10:01:01.456794+10:00",
              "time_zone": "+01:00",
              "format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
              "_name": "from",
              "boost": 1.1
            }
          }
        },
        {
          "range": {
            "availablity.availableTo": {
              "gt": "2017-07-21T10:01:01.456794+10:00",
              "time_zone": "+01:00",
              "format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
              "_name": "toDate",
              "boost": 1.1
            }
          }
        }
      ]
    }
  }
}

如果添加nameField作为匹配查询的字段,则

POST http://localhost:9200/projects/project/_search?pretty=true 
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "availablity.availableFrom": {
              "lte": "2017-07-21T10:02:23.896385+10:00",
              "time_zone": "+01:00",
              "format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
              "_name": "from",
              "boost": 1.1
            }
          }
        },
        {
          "range": {
            "availablity.availableTo": {
              "gt": "2017-07-21T10:02:23.896385+10:00",
              "time_zone": "+01:00",
              "format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
              "_name": "toDate",
              "boost": 1.1
            }
          }
        },
        {
          "match": {
            "contact.name": {
              "query": "free text"
            }
          }
        }
      ]
    }
  }
}

如果您确实要对Elasticsearch执行查询并查看结果,请从InMemoryConnection中删除ConnectionSettings

range查询是一种结构化查询,其中文档匹配或与谓词不匹配。因此,它可以包含在bool查询filter子句中,该子句将放弃计算得分并执行得更好。因为没有得分,所以不需要加速。

把它放在一起

var availableToField = Infer.Field<Project>(f => f.Availablity.AvailableTo);
var availableFromField = Infer.Field<Project>(f => f.Availablity.AvailableFrom);
var nameField = Infer.Field<Project>(f => f.Contact.Name);

var active_date_to = new DateRangeQuery
{
    Name = "toDate",
    Field = availableToField,
    GreaterThan = DateTime.Now,
    TimeZone = "+01:00",
    Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
var active_date_from = new DateRangeQuery
{
    Name = "from",
    Field = availableFromField,
    LessThanOrEqualTo = DateTime.Now,
    TimeZone = "+01:00",
    Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};

var ret = client.Search<Project>(s => s
    .Query(q =>
        +active_date_from &&
        +active_date_to && q
        .Match(d => d
            .Field(nameField)
            .Query("free text")
        )
    )
    .From(0)
    .Size(10)
);

您可能还希望以date_range type

的形式探索可用的建模