Git Repositories

105e5f250d16492d599088a0daa06513fff723e0
[xerox-elastic-poc.git] / src / main / java / com / viseo / xerox / elastic / Main.java
1 package com.viseo.xerox.elastic;
2
3 import org.hibernate.Session;
4 import org.hibernate.Transaction;
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
7
8 import javax.persistence.EntityManager;
9 import java.io.BufferedReader;
10 import java.io.IOException;
11 import java.io.InputStreamReader;
12 import java.net.URISyntaxException;
13 import java.nio.charset.StandardCharsets;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Scanner;
17
18 public class Main {
19
20     private static final double VISEO_LYON_LAT = 45.760399;
21     private static final double VISEO_LYON_LON = 4.851713;
22     private final EntityManager em;
23     private final ESJsonConfig esJsonConfig;
24     private static final Logger LOG = LoggerFactory.getLogger(Main.class);
25
26     public static void main(String[] args) {
27         System.setProperty("org.jboss.logging.provider", "slf4j");
28         try {
29             final String action;
30             if (args.length > 0) {
31                 action = args[0];
32             } else {
33                 action = "";
34             }
35             new Main().run(action);
36         } catch (Exception e) {
37             LOG.error(e.getMessage(), e);
38         } finally {
39             EntityManagerProvider.getInstance().getEmf().close();
40         }
41     }
42
43     private Main() {
44         em = EntityManagerProvider.getInstance().getEm();
45         esJsonConfig = new ESJsonConfig();
46     }
47
48     private void run(String action) throws Exception {
49         switch (action) {
50             case "create":
51                 createDb();
52                 break;
53             case "index":
54                 indexDb();
55                 break;
56             case "query":
57                 queryDb();
58                 break;
59             default:
60                 help();
61         }
62     }
63
64     private void help() {
65         LOG.info("Utiliser un des paramètres suivants:");
66         LOG.info("  create");
67         LOG.info("  index");
68         LOG.info("  query");
69     }
70
71     private void createDb() throws IOException {
72         final Session session = ((Session) em.getDelegate()).getSession();
73         try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/insert_data.sql"), StandardCharsets.UTF_8.name()))) {
74             final int maxLines = 100;
75             final List<String> lines = new ArrayList<>(maxLines);
76             String line;
77             while ((line = br.readLine()) != null) {
78                 lines.add(line);
79                 if (lines.size() == maxLines) {
80                     execSql(session, lines);
81                     lines.clear();
82                 }
83             }
84             if (lines.size() != 0) {
85                 execSql(session, lines);
86                 lines.clear();
87             }
88         }
89         session.close();
90     }
91
92     private void execSql(Session session, List<String> lines) {
93         Transaction tx = session.beginTransaction();
94         String sql = String.join("\n", lines).replace("{", "'||CHAR(123)||'").replace("}", "'||CHAR(125)||'");
95         session.createNativeQuery(sql).executeUpdate();
96         tx.commit();
97     }
98
99     private void indexDb() throws IOException {
100         ESRequest esRequest = new ESRequest(ESJsonConfig.ES_BASE_URL);
101         dropIndex(esRequest);
102         createIndexAndAnalyzer(esRequest);
103         paramMappings(esRequest, InterrestPoint.class, MobilityPoint.class);
104         final int bulkCount = 100;
105         List<Point> points = new ArrayList<>(bulkCount);
106         for (InterrestPoint point : em.createQuery("select p from InterrestPoint p", InterrestPoint.class).getResultList()) {
107             points.add(point);
108             if (points.size() == bulkCount) {
109                 bulkIndexPoints(esRequest, points);
110                 points.clear();
111             }
112         }
113         if (points.size() != 0) {
114             bulkIndexPoints(esRequest, points);
115             points.clear();
116         }
117         for (MobilityPoint point : em.createQuery("select p from MobilityPoint p", MobilityPoint.class).getResultList()) {
118             indexPoint(esRequest, point);
119         }
120     }
121
122     private void dropIndex(ESRequest esRequest) throws IOException {
123         esRequest.dropIndex(ESJsonConfig.INDEX_NAME);
124     }
125
126     private void createIndexAndAnalyzer(ESRequest esRequest) throws IOException {
127         esRequest.createIndex(esJsonConfig.getJsonIndex(), ESJsonConfig.INDEX_NAME);
128     }
129
130     @SafeVarargs
131     private final void paramMappings(ESRequest esRequest, Class<? extends Point>... classes) throws IOException {
132         for (Class<? extends Point> aClass : classes) {
133             esRequest.paramMapping(esJsonConfig.getJsonForMapping(), ESJsonConfig.INDEX_NAME, aClass.getSimpleName());
134         }
135     }
136
137     private void indexPoint(ESRequest esRequest, Point point) throws IOException {
138         esRequest.index(esJsonConfig.getJsonForIndexing(point), ESJsonConfig.INDEX_NAME, point.getClass().getSimpleName(), point.getId());
139     }
140
141     private void bulkIndexPoints(ESRequest esRequest, List<Point> points) throws IOException {
142         final List<String[]> jsonTuples = new ArrayList<>(points.size());
143         for (Point point : points) {
144             String jsonMetadata = esJsonConfig.getJsonMetadataForIndexing(ESJsonConfig.INDEX_NAME, point.getClass().getSimpleName(), point.getId());
145             String jsonForIndexing = esJsonConfig.getJsonForIndexing(point);
146             jsonTuples.add(new String[]{jsonMetadata, jsonForIndexing});
147         }
148         esRequest.bulkIndex(jsonTuples);
149     }
150
151     /**
152      * @see <a href="https://www.elastic.co/guide/en/elasticsearch/guide/2.x/asciifolding-token-filter.html">ascii folding</a>
153      */
154     private void queryDb() throws IOException, URISyntaxException {
155         try (Scanner scanner = new Scanner(System.in, "UTF-8")) {
156             while (true) {
157                 final double latitude = getDouble(scanner, "Latitude", VISEO_LYON_LAT);
158                 final double longitude = getDouble(scanner, "Longitude", VISEO_LYON_LON);
159                 final boolean scoreByGeo = getBoolean(scanner, "Privilégier la recherche par proximité géographique", false);
160                 final boolean useGeo = !scoreByGeo && getBoolean(scanner, "Affiner la recherche par proximité géographique", false);
161                 esJsonConfig.setSearchMode(useGeo ? SearchMode.BY_SCORE_AND_PROXIMITY : scoreByGeo ? SearchMode.BY_PROXIMITY : SearchMode.BY_SCORE);
162                 final boolean fuzziness = getBoolean(scanner, "Avec fuzziness", false);
163                 esJsonConfig.setFuzziness(fuzziness);
164                 String queryString;
165                 while (true) {
166                     System.out.print("Query : ");
167                     queryString = scanner.nextLine();
168                     if (queryString.isEmpty()) {
169                         break;
170                     }
171                     List<Point> points = queryES(queryString, latitude, longitude);
172                     getAndPrintPoints(points);
173                 }
174                 if (getBoolean(scanner, "Quitter", true)) {
175                     break;
176                 } else {
177                     System.out.println("**********");
178                 }
179             }
180         }
181     }
182
183     private boolean getBoolean(Scanner scanner, String label, boolean def) {
184         System.out.print(String.format("%s [%s] ? ", label, def ? "O/n" : "o/N"));
185         String line = scanner.nextLine().toLowerCase().replace("o", Boolean.TRUE.toString());
186         if (line.isEmpty()) {
187             return def;
188         } else {
189             return Boolean.parseBoolean(line);
190         }
191     }
192
193     private double getDouble(Scanner scanner, String label, double def) {
194         System.out.print(String.format("%s [%f] : ", label, def));
195         String line = scanner.nextLine().replace(".", ",");
196         if (line.isEmpty()) {
197             return def;
198         } else {
199             return Double.parseDouble(line);
200         }
201     }
202
203     private List<Point> queryES(String queryString, double latitude, double longitude) throws IOException, URISyntaxException {
204         String jsonRequest = esJsonConfig.getJsonQuery(queryString, latitude, longitude);
205         LOG.debug(jsonRequest);
206         String jsonResult = new ESRequest(ESJsonConfig.ES_BASE_URL).find(jsonRequest, ESJsonConfig.INDEX_NAME, queryString);
207         LOG.debug(jsonResult);
208         return esJsonConfig.parseJsonResult(jsonResult);
209     }
210
211     private void getAndPrintPoints(List<Point> points) {
212         for (Point point : points) {
213             Class<? extends Point> pointClass = point.getClass();
214             double score = point.getScore();
215             Double distanceKm = point.getDistanceKm();
216             point = em.createQuery(String.format("select p from %s p where p.id = :id", pointClass.getSimpleName()), pointClass).setParameter("id", point.getId()).getSingleResult();
217             point.setScore(score);
218             point.setDistanceKm(distanceKm);
219             LOG.info(point.toString());
220         }
221     }
222 }