1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.entity;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.codelibs.core.lang.StringUtil;
24 import org.codelibs.core.stream.StreamUtil;
25 import org.codelibs.fess.exception.InvalidQueryException;
26 import org.codelibs.fess.mylasta.direction.FessConfig;
27 import org.codelibs.fess.util.ComponentUtil;
28 import org.lastaflute.core.message.UserMessages;
29 import org.opensearch.index.query.BoolQueryBuilder;
30 import org.opensearch.index.query.QueryBuilder;
31 import org.opensearch.index.query.QueryBuilders;
32
33 import jakarta.servlet.http.HttpServletRequest;
34
35
36
37
38
39
40
41 public class GeoInfo {
42
43
44 private QueryBuilder builder;
45
46
47
48
49
50
51
52
53
54 public GeoInfo(final HttpServletRequest request) {
55
56 final FessConfig fessConfig = ComponentUtil.getFessConfig();
57 final String[] geoFields = fessConfig.getQueryGeoFieldsAsArray();
58 final Map<String, List<QueryBuilder>> geoMap = new HashMap<>();
59
60 StreamUtil.stream(request.getParameterMap())
61 .of(stream -> stream.filter(e -> e.getKey().startsWith("geo.") && e.getKey().endsWith(".point")).forEach(e -> {
62 final String key = e.getKey();
63 for (final String geoField : geoFields) {
64 if (key.startsWith("geo." + geoField + ".")) {
65 final String distanceKey = key.replaceFirst(".point$", ".distance");
66 final String distance = request.getParameter(distanceKey);
67 if (StringUtil.isNotBlank(distance)) {
68 StreamUtil.stream(e.getValue()).of(s -> s.forEach(pt -> {
69 List<QueryBuilder> list = geoMap.get(geoField);
70 if (list == null) {
71 list = new ArrayList<>();
72 geoMap.put(geoField, list);
73 }
74 final String[] values = pt.split(",");
75 if (values.length != 2) {
76 throw new InvalidQueryException(
77 messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
78 "Invalid geo point: " + pt);
79 }
80 try {
81 final double lat = Double.parseDouble(values[0]);
82 final double lon = Double.parseDouble(values[1]);
83 list.add(QueryBuilders.geoDistanceQuery(geoField).distance(distance).point(lat, lon));
84 } catch (final Exception ex) {
85 throw new InvalidQueryException(
86 messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
87 ex.getLocalizedMessage(), ex);
88 }
89 }));
90 }
91 break;
92 }
93 }
94 }));
95
96 final QueryBuilder[] queryBuilders = geoMap.values().stream().map(list -> {
97 if (list.size() == 1) {
98 return list.get(0);
99 }
100 if (list.size() > 1) {
101 final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
102 list.forEach(boolQuery::should);
103 return boolQuery;
104 }
105 return null;
106 }).filter(q -> q != null).toArray(n -> new QueryBuilder[n]);
107
108 if (queryBuilders.length == 1) {
109 builder = queryBuilders[0];
110 } else if (queryBuilders.length > 1) {
111 final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
112 StreamUtil.stream(queryBuilders).of(stream -> stream.forEach(boolQuery::must));
113 builder = boolQuery;
114 }
115
116 }
117
118
119
120
121
122
123 public QueryBuilder toQueryBuilder() {
124 return builder;
125 }
126
127 }