简体   繁体   中英

Elastic search nest dynamic query with object initializer NEST 5.x

Hi I'm a new to elastic nest API and I'm using nest 5.x. I'm currently developing some kind of advanced search page so when user doesn't check a criteria i don't have to include that filter on my query. I'm trying to combine 2 queries under must operator with object initializer approach using nest. How to achieve it? I'm following the example on [ 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" } && new TermQuery { Field = Field(p => p.Name), Value = "y" } });

But it doesnt work cause Field class doesnt accept type arguments.

I also tried to followed this approach from this topic [ Nest Elastic - Building Dynamic Nested Query

here is my code

  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; } } 

But that returns zero result. How to achieve this? Thx anyway.

EDIT :

This is the params variabel definition. Its apoco model of search keywords

 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 is a poco model of search result. Its actualy a document type which is stored on the elastic server

 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); } } } 

But it doesnt work cause Field class doesnt accept type arguments.

You need to ensure that you include a using static directive for Nest.Infer ie

using static Nest.Infer;

with the rest of the using directives.

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

No need to wrap in a Must() , just do

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

which will wrap both queries in a bool query must clause. You also don't need to null check andQuery because NEST is smart enough to not combine the two queries if either or both are 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 has the concept of conditionless queries so you don't need to check it queries.queryfields is null or empty, simply build the query and add it to andQuery . So it would become

var val = queries.queryfields;

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

Aside

All of the NEST documentation is generated from source code; you can trace back to the original source file by clicking on any edit link within the documentation. This will take you to a github page, such as this one for bool queries . From here, the document contains an important note that links back to the original source .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM