使用对象初始值设定项NEST 5.x的弹性搜索嵌套动态查询

时间:2017-07-22 22:59:40

标签: c# elasticsearch dynamic nest booleanquery

您好我是弹性嵌套API的新手,我使用的是嵌套5.x.我目前正在开发某种高级搜索页面,因此当用户没有检查条件时,我不必在我的查询中包含该过滤器。我试图在使用nest的对象初始化方法下将must运算符下的2个查询组合起来。怎么实现呢?我跟随[https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html]

上的示例
  

var secondSearchResponse = client.Search(new   SearchRequest {       Query = new TermQuery {Field = Field(p => p.Name),Value =" x" }&&               新的TermQuery {Field = Field(p => p.Name),Value =" y" }});

但它不起作用,因为Field类不接受类型参数。

我也试图从这个主题中采用这种方法 [Nest Elastic - Building Dynamic Nested Query

这是我的代码

    public HttpResponseMessage GetSearchResult([FromUri] SearchModels queries)
    {
        try
        {
            ///
            string result = string.Empty;
            result += "queryfields + " + queries.queryfields == null ? string.Empty : queries.queryfields;
            result += "datefrom + " + queries.datefrom == null ? string.Empty : queries.datefrom;
            result += "dateto + " + queries.dateto == null ? string.Empty : queries.dateto;
            result += "emitentype + " + queries.emitentype == null ? string.Empty : queries.emitentype;

            QueryContainer andQuery = null;

            //List<QueryContainer> QueryContainers = new List<QueryContainer>();

            IDXNetAnnouncement record = new IDXNetAnnouncement
            {
                kode_emiten = queries.kodeemiten
            };

            #region keyword
            if (!string.IsNullOrEmpty(queries.queryfields))
            {
                var val = queries.queryfields;

                TermQuery tq = new TermQuery
                {
                    Field = queries.queryfields,
                    Value = val
                };

                if (andQuery == null)
                    andQuery = tq;
                else
                    andQuery &= tq;

                //QueryContainers.Add(tq);
            }
            #endregion keyword

            #region kodeemiten
            if (!string.IsNullOrEmpty(queries.kodeemiten))
            {
                var val = queries.kodeemiten;

                TermQuery tq = new TermQuery
                {
                    Name = "kode_emiten",
                    Field = record.kode_emiten,
                    Value = val
                };

                if (andQuery == null)
                    andQuery = tq;
                else
                    andQuery &= tq;

                //QueryContainers.Add(tq);
            }
            #endregion            

            #region date
            if (!string.IsNullOrEmpty(queries.datefrom) && !string.IsNullOrEmpty(queries.dateto))
            {
                DateRangeQuery dq = new DateRangeQuery();
                dq.Name = "tglpengumuman";
                dq.LessThanOrEqualTo = DateMath.Anchored(queries.dateto);
                dq.GreaterThanOrEqualTo = DateMath.Anchored(queries.datefrom);
                dq.Format = "dd/mm/yyyy";

                if (andQuery == null)
                    andQuery = dq;
                else
                    andQuery &= dq;

                //QueryContainers.Add(dq);
            }
            #endregion keyword

            var reqs = (ISearchResponse<IDXNetAnnouncement>)null;

            if (andQuery != null)
            {
                reqs = conn.client.Search<IDXNetAnnouncement>(s => s
                        .AllIndices()
                        .AllTypes()
                        .From(queries.indexfrom)
                        .Size(queries.pagesize)
                        .Query(q => q.Bool(qb => qb.Must(m => m.MatchAll() && andQuery))));
                //var json = conn.client.Serializer.SerializeToString(reqs.ApiCall.ResponseBodyInBytes);
            }
            else
            {
                reqs = conn.client.Search<IDXNetAnnouncement>(s => s
                       .AllIndices()
                       .AllTypes()
                       .From(queries.indexfrom)
                       .Size(queries.pagesize)
                       .Query(m => m.MatchAll()));
            }

            //var reqstring = Encoding.UTF8.GetString(conn.client.);
            var reslts = this.conn.client.Serializer.SerializeToString(reqs,SerializationFormatting.Indented);

            var resp = new HttpResponseMessage()
            {
                Content = new StringContent(reslts)
            };
            resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            return resp;
        }
        catch (Exception e)
        {
            var resp = new HttpResponseMessage()
            {
                Content = new StringContent(e.ToString())
            };
            resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            return resp;
        }
    }

但是返回零结果。怎么做到这一点?无论如何,谢谢。

编辑:

这是params变量定义。它的搜索关键字的apoco模型

public class SearchModels
{
    public string queryfields { get; set; }
    public string datefrom { get; set; }
    public string dateto { get; set; }
    public string emitentype { get; set; }
    public string kodeemiten { get; set; }
    public string issuercode { get; set; }
    public int indexfrom { get; set; }
    public int pagesize { get; set; }

}

IDXNetAnnouncement是搜索结果的poco模型。它实际上是一个存储在弹性服务器上的文档类型

public class IDXNetAnnouncement 
{
    public string perihalpengumuman { get; set; }
    public string attachments { get; set; }
    public string createddate { get; set; }
    public bool efekemiten_spei { get; set; }
    public string jmsxgroupid { get; set; }
    public string tglpengumuman { get; set; }
    public object errordescription { get; set; }
    public string ESversion { get; set; }
    public int oldfinalid { get; set; }
    public bool efekemiten_etf { get; set; }
    public object errorcode { get; set; }
    public string jenisemiten { get; set; }
    public int pkid { get; set; }
    public string judulpengumuman { get; set; }
    public string form_id { get; set; }
    public bool efekemiten_eba { get; set; }
    public string jenispengumuman { get; set; }
    public string nopengumuman { get; set; }
    public string kode_emiten { get; set; }
    public string divisi { get; set; }
    public string EStimestamp { get; set; }
    public bool efekemiten_obligasi { get; set; }
    public long finalid { get; set; }
    public bool efekemiten_saham { get; set; }
    public string kodedivisi { get; set; }
    public string SearchTerms
    {
        get
        {
            return string.Format("{0} {1} {2}", judulpengumuman, kode_emiten, nopengumuman);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

  

但它不起作用,因为Field类不接受类型参数。

您需要确保为Nest.Infer包括using static directive,即

using static Nest.Infer;

使用其余的using指令。

  

.Query(q =&gt; q.Bool(qb =&gt; qb.Must(m =&gt; m.MatchAll()&amp;&amp; andQuery))));

无需包裹Must(),只需执行

.Query(q => q.MatchAll() && andQuery)

将在bool查询must子句中包装两个查询。您也不需要null检查andQuery,因为如果其中一个或两个都是null,NEST足够聪明,不能合并这两个查询。

if (!string.IsNullOrEmpty(queries.queryfields))
{
    var val = queries.queryfields;

    TermQuery tq = new TermQuery
    {
        Field = queries.queryfields,
        Value = val
    };

    if (andQuery == null)
        andQuery = tq;
    else
        andQuery &= tq;

    //QueryContainers.Add(tq);
}

NEST具有conditionless queries的概念,因此您无需检查它queries.queryfields是空还是空,只需构建查询并将其添加到andQuery即可。所以它会成为

var val = queries.queryfields;

andQuery &= new TermQuery
{
    Field = queries.queryfields,
    Value = val
};

除了

所有NEST文档都是从源代码生成的;您可以通过单击文档中的任何编辑链接追溯回原始源文件。这将带您进入github页面such as this one for bool queries。从这里开始,该文档包含一个重要的注释,链接回original source