Git Repositories

Initial
[xerox-elastic-poc.git] / src / main / java / com / viseo / xerox / elastic / ESJsonConfig.java
1 package com.viseo.xerox.elastic;
2
3 import com.fasterxml.jackson.core.JsonFactory;
4 import com.fasterxml.jackson.core.JsonGenerator;
5 import com.fasterxml.jackson.databind.JsonNode;
6 import com.fasterxml.jackson.databind.ObjectMapper;
7 import com.fasterxml.jackson.databind.ObjectWriter;
8
9 import java.io.IOException;
10 import java.io.StringWriter;
11 import java.util.ArrayList;
12 import java.util.Iterator;
13 import java.util.List;
14
15 /**
16  * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html">search-uri-request</a>
17  * @see <a href="https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping-intro.html">mapping-intro</a>
18  * @see <a href="https://www.elastic.co/guide/en/elasticsearch/guide/2.x/unicode-normalization.html">unicode-normalization</a>
19  * @see <a href="https://www.elastic.co/guide/en/elasticsearch/guide/2.x/using-synonyms.html">using-synonyms</a>
20  */
21 public class ESJsonConfig {
22     public static final String ES_BASE_URL = "http://localhost:9200";
23     public static final String INDEX_NAME = "xerox";
24     /**
25      * Relative to Elastic-Search <code>config</code> directory
26      */
27     public static final String SYNONYM_TXT_FILE = "analysis/synonym.txt";
28
29     private JsonFactory factory;
30     private ObjectWriter writer;
31
32     public ESJsonConfig() {
33         factory = new JsonFactory();
34         writer = new ObjectMapper(factory).writer();
35     }
36
37     public String getJsonIndex() throws IOException {
38         StringWriter stringWriter = new StringWriter();
39         JsonGenerator jg = factory.createGenerator(stringWriter);
40         // @formatter:off
41         jg.writeStartObject();
42             jg.writeObjectFieldStart("settings");
43                 jg.writeObjectFieldStart("index");
44                     jg.writeObjectFieldStart("analysis");
45                         jg.writeObjectFieldStart("analyzer");
46                             jg.writeObjectFieldStart("custom_french_analyzer");
47                                 jg.writeStringField("type","custom");
48                                 jg.writeStringField("tokenizer","standard");
49                                 jg.writeArrayFieldStart("filter");
50                                     jg.writeString("trim");
51                                     jg.writeString("french_elision");
52                                     jg.writeString("lowercase");
53                                     jg.writeString("asciifolding");
54                                     jg.writeString("synonym");
55                                     jg.writeString("french_stop");
56                                     jg.writeString("french_stemmer");
57                                 jg.writeEndArray();
58                             jg.writeEndObject();
59                         jg.writeEndObject();
60                         jg.writeObjectFieldStart("filter");
61                             jg.writeObjectFieldStart("french_elision");
62                                 jg.writeStringField("type","elision");
63                                 jg.writeBooleanField("articles_case", true);
64                                 jg.writeArrayFieldStart("articles");
65                                     for (String article : new String[] {"l", "m", "t", "qu", "n", "s", "j", "d", "c", "jusqu", "quoiqu", "lorsqu", "puisqu"}) {
66                                         jg.writeString(article);
67                                     }
68                                 jg.writeEndArray();
69                             jg.writeEndObject();
70                             jg.writeObjectFieldStart("french_stop");
71                                 jg.writeStringField("type","stop");
72                                 jg.writeStringField("stopwords","_french_");
73                             jg.writeEndObject();
74                             jg.writeObjectFieldStart("french_stemmer");
75                                 jg.writeStringField("type","stemmer");
76                                 jg.writeStringField("language","light_french");
77                             jg.writeEndObject();
78                             jg.writeObjectFieldStart("synonym");
79                                 jg.writeStringField("type","synonym");
80                                 jg.writeStringField("synonyms_path",SYNONYM_TXT_FILE);
81                                 jg.writeBooleanField("ignore_case",true);
82                             jg.writeEndObject();
83                         jg.writeEndObject();
84                     jg.writeEndObject();
85                 jg.writeEndObject();
86             jg.writeEndObject();
87         jg.writeEndObject();
88         // @formatter:on
89         jg.close();
90         return stringWriter.toString();
91     }
92
93     /**
94      * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/2.4/geo-point.html">geo-point</a>
95      * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/2.4/multi-fields.html">multi-fields</a>
96      * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/2.4/analysis-lang-analyzer.html#french-analyzer">french-analyzer</a>
97      */
98     public String getJsonForMapping() throws IOException {
99         StringWriter stringWriter = new StringWriter();
100         JsonGenerator jg = factory.createGenerator(stringWriter);
101         // @formatter:off
102         jg.writeStartObject();
103             jg.writeObjectFieldStart("properties");
104                 addMapperForGeoLocation(jg, "geo_point");
105                 addMapperForFrenchText(jg, "name");
106                 addMapperForFrenchText(jg, "town");
107             jg.writeEndObject();
108         jg.writeEndObject();
109         // @formatter:on
110         jg.close();
111         return stringWriter.toString();
112     }
113
114     private void addMapperForGeoLocation(JsonGenerator jg, @SuppressWarnings("SameParameterValue") String fieldName) throws IOException {
115         jg.writeObjectFieldStart("location");
116         jg.writeStringField("type", fieldName);
117         jg.writeBooleanField("lat_lon", true);
118         jg.writeEndObject();
119     }
120
121     private void addMapperForFrenchText(JsonGenerator jg, String fieldName) throws IOException {
122         // @formatter:off
123         jg.writeObjectFieldStart(fieldName);
124             jg.writeStringField("type", "string");
125             jg.writeObjectFieldStart("fields");
126                 jg.writeObjectFieldStart("french");
127                     jg.writeStringField("type", "string");
128                     jg.writeStringField("analyzer", "custom_french_analyzer");
129                 jg.writeEndObject();
130             jg.writeEndObject();
131         jg.writeEndObject();
132         // @formatter:on
133     }
134
135     public String getJsonForIndexing(final Point point) throws IOException {
136         StringWriter stringWriter = new StringWriter();
137         writer.writeValue(stringWriter, point);
138         return stringWriter.toString();
139     }
140
141     public String getJsonQuery(String queryString, double latitude, double longitude) throws IOException {
142         StringWriter stringWriter = new StringWriter();
143         JsonGenerator jg = factory.createGenerator(stringWriter);
144         // @formatter:off
145         jg.writeStartObject();
146             jg.writeObjectFieldStart("query");
147                 jg.writeObjectFieldStart("multi_match");
148                     jg.writeStringField("type", "best_fields");
149                     jg.writeStringField("query", queryString);
150                     jg.writeArrayFieldStart("fields");
151                         jg.writeString("name");
152                         jg.writeString("name.french");
153                         jg.writeString("town");
154                         jg.writeString("town.french");
155                     jg.writeEndArray();
156                     jg.writeStringField("fuzziness", "AUTO");
157                 jg.writeEndObject();
158             jg.writeEndObject();
159             jg.writeArrayFieldStart("sort");
160                 jg.writeStartObject();
161                     jg.writeObjectFieldStart("_geo_distance");
162                         jg.writeObjectFieldStart("location");
163                             jg.writeNumberField("lat", latitude);
164                             jg.writeNumberField("lon", longitude);
165                         jg.writeEndObject();
166                         jg.writeStringField("unit", "km");
167                     jg.writeEndObject();
168                 jg.writeEndObject();
169                 jg.writeStartObject();
170                     jg.writeObjectFieldStart("_type");
171                         jg.writeStringField("order", "asc"); // InterrestPoint before MobilityPoint
172                     jg.writeEndObject();
173                 jg.writeEndObject();
174             jg.writeEndArray();
175             jg.writeBooleanField("track_scores", true);
176         jg.writeEndObject();
177         // @formatter:on
178         jg.close();
179         return stringWriter.toString();
180     }
181
182     public List<Point> parseJsonResult(String json) throws IOException {
183         ObjectMapper mapper = new ObjectMapper();
184         List<Point> points = new ArrayList<>();
185         JsonNode rootNode = mapper.readValue(json, JsonNode.class);
186         JsonNode hitsNode = rootNode.get("hits");
187         JsonNode hits = hitsNode.get("hits");
188         Iterator<JsonNode> elements = hits.elements();
189         while (elements.hasNext()) {
190             JsonNode hitNode = elements.next();
191             String type = hitNode.get("_type").asText();
192             final Point point;
193             Iterator<JsonNode> sortItems;
194             switch (type) {
195                 case "InterrestPoint":
196                     point = new InterrestPoint();
197                     break;
198                 case "MobilityPoint":
199                     point = new MobilityPoint();
200                     break;
201                 default:
202                     point = null;
203             }
204             if (point != null) {
205                 point.setId(hitNode.get("_id").asLong());
206                 sortItems = hitNode.get("sort").elements();
207                 point.setDistanceKm(sortItems.next().asDouble());
208                 points.add(point);
209             }
210         }
211         return points;
212     }
213 }