Динамический запрос с упругим поиском с помощью инициализатора объектов NEST 5.x

Привет, я новичок в API эластичных гнезд и использую гнездо 5.x. В настоящее время я разрабатываю какую-то страницу расширенного поиска, поэтому, когда пользователь не проверяет критерии, мне не нужно включать этот фильтр в мой запрос. Я пытаюсь объединить 2 запроса под оператором must с подходом инициализатора объекта, используя гнездо. Как этого добиться? Я следую примеру на [ https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html]

var secondSearchResponse = client.Search (новый SearchRequest { Query = новый TermQuery { Field = Field(p => p.Name), Value = "x" } && new TermQuery { Field = Field(p => p.Name), Value = "y" } });

Но это не работает, потому что класс Field не принимает аргументы типа.

Я также пытался следовать этому подходу из этой темы [ Nest Elastic - Построение динамического вложенного запроса

вот мой код

    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. Его апоко модель поиска по ключевым словам

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 - это модель результатов поиска. На самом деле это тип документа, который хранится на эластичном сервере.

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 ответ

Но это не работает, потому что класс Field не принимает аргументы типа.

Вы должны убедиться, что вы используете статическую директиву Nest.Infer т.е.

using static Nest.Infer;

с остальными директивами использования.

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

Не нужно завернуть в Must(), просто делать

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

который обернет оба запроса в bool запрос must пункт. Вам также не нужно null проверять andQuery потому что NEST достаточно умен, чтобы не объединять два запроса, если один или оба null,

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 имеет концепцию безусловных запросов, поэтому вам не нужно проверять это queries.queryfields является нулевым или пустым, просто создайте запрос и добавьте его в andQuery, Так бы и стало

var val = queries.queryfields;

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

В сторону

Вся документация NEST генерируется из исходного кода; Вы можете вернуться к исходному файлу, нажав на любую ссылку редактирования в документации. Это приведет вас к странице GitHub, такой как эта для запросов bool. Отсюда, документ содержит важную заметку, которая ссылается на первоисточник.

Другие вопросы по тегам