Objective
Prior to the project to do Elasticsearch related development, although the use of third-party components plainelastic.net, but because of the unfamiliar usage at the time, and chose their own stitching query statements. For example:
stringQuerygroup ="{\ "query\": {\ "match\": {\ "roomid\": \ "Friend_12686_10035\" }}}"; //keyword Query stringQuerykeyword ="{\ "query\": {\ "match_phrase\": {\ "content\": {\ "query\": \ ""+ keyword +"\ ", \" Slop\ ": 0} }}"; //whether picture query stringQueryimg ="{\ "term\": {\ "isimg\": true}}"; //whether to include file queries stringQueryfile ="{\ "term\": {\ "isfile\": true}}"; //greater than less than a certain time period query stringQuerytimerange ="{\ "range\": {\ "addtime\": {\ "gt\": \ ""+ St +"\ ", \" lt\ ": \""+ et +"\" }} }"; //greater than a certain time stringQuerytimerangegt ="{\ "range\": {\ "addtime\": {\ "gt\": \ ""+ St +"\"}} }"; //less than a certain time stringQuerytimerangelt ="{\ "range\": {\ "addtime\": {\ "lt\": \ ""+ et +"\" }} }";
Then slowly looked at the source code of the component, want to make it easy to implement, to see what the principle.
Analysis
Let's start with a simple little example: demo in plainelastic:
string New Querybuilder<tweet> () // . Query (q = q // {"Query": {"term": {"User": "Somebody"}}} . Term (t = t . Field (Tweet= tweet. User). Value ("somebody")) . Build ();
As you can see, the construction of query statements is very flexible, directly in the form of expressions, and finally through the build method to generate the corresponding query statements, so, according to gourd painting scoop, start it. In fact, no matter how to write the statement, the end is the concatenation of the string, generating the final query statement. So let's start with the simplest term query. For example, a query statement is {"query": {"term": {"name": "Zhangsan"}}}, the meaning of this statement is to query the data named Zhangsan. (Requires reader to understand Elasticsearch query syntax)
The
does not consider encapsulation, directly create a new class, called Termfilter, the internal implementation of the term language constructs. Because of the need for chained calls, the inside method generally returns this.
private dictionary<string , object > _terms;
public Termfilter () {_terms = new dictionary<string , object > (); public termfilter KeyValue (string key, object value) {_terms. ADD (key, value); return this ; }
As shown in the preceding code, when we call the KeyValue method, we pass in the key and value, which is added to the internal dictionary. Then rewrite the ToString method to construct the term statement
Private voidBuild () {StringBuilder str=NewStringBuilder (); inti =0; foreach(keyvaluepair<string,Object> KVinch_terms) {str. Append ("{\ "term\": {\ ""+ KV. Key +"\":"+ KV. Value +"}}"); if(I >=0&& i < _terms. Count-1) {str. Append (","); } I++; } _condition=Str. ToString (); } Public Override stringToString () {Build (); return Base. ToString (); }
Traversal dictionary, constructs the term statement, after the term constructs, we need to add a query in the outer layer, because the query is universal, so also need to extract. Thus, there is another class, called filter, this is the entrance to the query, there are two methods, a bool method, a Query method:
PublicFilter () {}// PublicFilter Bool (Func<boolfilter, boolfilter>Boolfunc) { stringBoolfuncresult = Boolfunc (NewBoolfilter ()). ToString (); _condition="{\ "query\": {\ "filtered\": {\ "Filter\": {"+ Boolfuncresult +"}}}"; return This; } PublicFilter Query (Func<boolfilter, boolfilter>Boolfunc) { stringBoolfuncresult = Boolfunc (NewBoolfilter ()). ToString (); _condition="{\ "query\":"+Boolfuncresult; return This; }
Directly look at the query method, the parameters inside the func<boolfilter,boolfilter> boolfunc, OK, here the boss finally came out, is the core class, boolfilter, its internal implementation, Must,shoud, Mustnot,and,or, and other methods. And of course there are term. We look directly at the term method.
Public Boolfilter term (func<termfilter, termfilter> termfunc) { praparecondition (); + = Termfunc (new termfilter ()) ; return This ; }
Similarly, because the chain call, or return this, in the above code because TERMFUNC returns a Termfilter object, and then ToString, it is equivalent to append the corresponding term statement. The ToString method eventually returns the value of the _condition field. Well, I guess you're getting dizzy, it's okay, we're looking at the last class, we can do the actual combat.
Public Querycreator filter (Func<filter, filter> filter) { + = filter (new filter ()) ; return This ; }
Well, here, the code is basically over. Re-comb it again:
First, the outermost code calls the filter method, the filter implements the Query method, the query internally passed in the Boolfilter parameter, in the call term method, finally by the termfilter implementation of the statement construction, so, the external final code calls up this way.
varresult = Creator. Filter (f =//the query method is called inside the filter,F.query (q =//query calls the term method of BoolfilterQ.term (t =//Boolfilter also calls Termfilter's KeyValue methodT.keyvalue ("name","Zhangsan")))) . Buildbeautiful ();//and finally build the results we want.
For example, the From and size are the default. Let's get a little more complicated. For example, in a user table, want to query the user Type 3 and the region for Beijing and meet the age is 20 years old or work experience for 1 years of users. And according to the name of the flashback sort, paging to the 3rd page of 20 data.
First of all, here we use and query, and also include or query. The construction statements are as follows:
varresult = Creator. Filter (f =F.bool (b=//BOOL QueryB.must (M =//must, must meet the conditionsM.and (A =//and QueryA.term (t =//Constructing query ConditionsT.keyvalue ("type",3). KeyValue (" Area","Beijing")). Or (o= o.term (t1 = t1. KeyValue (" Age", -). KeyValue ("Experience",1))))))).//or query, construct a query conditionPage (3).//Page NumberSize ( -).//size per pageOrderbydesc ("name").//Name Flashback SortBuildbeautiful ();//Create a query statement based on a previous condition
Haha, is not a bit around ah, in fact, to use this, or to point ES query syntax, like SQL statements, you do not understand, is not found east. In this way we can avoid the manual write ES query statements, as long as the code is simple to make a good, but I still obediently use the third party components, I wrote too slag ...
Look at the resulting statement:
All right, here we go. As a summary of their own research.
Development of Elasticsearch query Statement builder for func<t,t> application