├── .gitignore
├── .travis.yml
├── README.md
├── gpl.txt
├── pom.xml
└── src
├── main
├── assemblies
│ └── plugin.xml
├── java
│ └── com
│ │ └── graphaware
│ │ └── es
│ │ └── gas
│ │ ├── GraphAidedSearch.java
│ │ ├── GraphAidedSearchFilter.java
│ │ ├── GraphAidedSearchModule.java
│ │ ├── GraphAidedSearchPlugin.java
│ │ ├── annotation
│ │ ├── SearchBooster.java
│ │ └── SearchFilter.java
│ │ ├── booster
│ │ ├── SearchResultBooster.java
│ │ ├── SearchResultCypherBooster.java
│ │ ├── SearchResultExternalBooster.java
│ │ └── SearchResultNeo4jBooster.java
│ │ ├── cypher
│ │ ├── CypherBoltHttpEndPoint.java
│ │ ├── CypherEndPoint.java
│ │ ├── CypherEndPointBuilder.java
│ │ ├── CypherHttpEndPoint.java
│ │ ├── CypherResult.java
│ │ ├── CypherSettingsReader.java
│ │ └── ResultRow.java
│ │ ├── domain
│ │ ├── ClauseConstants.java
│ │ ├── ExternalResult.java
│ │ └── IndexInfo.java
│ │ ├── filter
│ │ ├── SearchResultCypherFilter.java
│ │ └── SearchResultFilter.java
│ │ ├── modifier
│ │ ├── PrivilegedSearchResultModifier.java
│ │ └── SearchResultModifier.java
│ │ ├── util
│ │ ├── Instantiator.java
│ │ ├── NumberUtil.java
│ │ ├── ParamUtil.java
│ │ ├── PluginClassLoader.java
│ │ └── UrlUtil.java
│ │ └── wrap
│ │ ├── ActionListenerWrapper.java
│ │ ├── CannotWrapException.java
│ │ ├── GraphAidedSearchActionListenerWrapper.java
│ │ └── WrappingActionListener.java
└── plugin-metadata
│ ├── plugin-descriptor.properties
│ └── plugin-security.policy
└── test
├── java
└── com
│ └── graphaware
│ └── es
│ └── gas
│ ├── EmbeddedGraphDatabaseServerTest.java
│ ├── GraphAidedSearchFilterTest.java
│ ├── GraphAidedSearchIntegrationBoltTest.java
│ ├── GraphAidedSearchIntegrationTest.java
│ ├── GraphAidedSearchNeo4jIntegrationTest.java
│ ├── GraphAidedSearchTest.java
│ ├── JestMsgResult.java
│ ├── MockServerTest.java
│ ├── booster
│ ├── GraphBoosterTest.java
│ ├── SearchResultCypherBoltBoosterTest.java
│ ├── SearchResultCypherBoosterTest.java
│ └── SearchResultNeo4jBoosterTest.java
│ ├── domain
│ ├── CypherEndpointBoltTest.java
│ ├── CypherEndpointTest.java
│ ├── CypherEndpointUnitTest.java
│ ├── ExternalResultTest.java
│ ├── ExternalResultUnitTest.java
│ └── TestIndexInfo.java
│ ├── filter
│ ├── GraphFilterTest.java
│ └── SearchResultCypherFilterTest.java
│ ├── stubs
│ ├── CypherSearchResultTestBooster.java
│ ├── CypherSearchResultTestFilter.java
│ └── SearchResultTestBooster.java
│ └── util
│ ├── ClauseConstantsTest.java
│ ├── NumberUtilTest.java
│ ├── TestHttpClient.java
│ └── UrlUtilTest.java
└── resources
├── demo-data-reduced.cyp
├── demo-data.cyp
├── graphgen-test-data.cyp
├── neo4j-elasticsearch-reco.properties
├── neo4j-elasticsearch.properties
└── neo4j-server-es.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io
2 |
3 | ### Project ###
4 | data/
5 |
6 | ### Intellij ###
7 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
8 |
9 | *.iml
10 |
11 | ## Directory-based project format:
12 | .idea/
13 | # if you remove the above rule, at least ignore the following:
14 |
15 | # User-specific stuff:
16 | # .idea/workspace.xml
17 | # .idea/tasks.xml
18 | # .idea/dictionaries
19 |
20 | # Sensitive or high-churn files:
21 | # .idea/dataSources.ids
22 | # .idea/dataSources.xml
23 | # .idea/sqlDataSources.xml
24 | # .idea/dynamic.xml
25 | # .idea/uiDesigner.xml
26 |
27 | # Gradle:
28 | # .idea/gradle.xml
29 | # .idea/libraries
30 |
31 | # Mongo Explorer plugin:
32 | # .idea/mongoSettings.xml
33 |
34 | ## File-based project format:
35 | *.ipr
36 | *.iws
37 |
38 | ## Plugin-specific files:
39 |
40 | # IntelliJ
41 | /out/
42 |
43 | # mpeltonen/sbt-idea plugin
44 | .idea_modules/
45 |
46 | # JIRA plugin
47 | atlassian-ide-plugin.xml
48 |
49 | # Crashlytics plugin (for Android Studio and IntelliJ)
50 | com_crashlytics_export_strings.xml
51 | crashlytics.properties
52 | crashlytics-build.properties
53 |
54 |
55 | ### OSX ###
56 | .DS_Store
57 | .AppleDouble
58 | .LSOverride
59 |
60 | # Icon must end with two \r
61 | Icon
62 |
63 |
64 | # Thumbnails
65 | ._*
66 |
67 | # Files that might appear in the root of a volume
68 | .DocumentRevisions-V100
69 | .fseventsd
70 | .Spotlight-V100
71 | .TemporaryItems
72 | .Trashes
73 | .VolumeIcon.icns
74 |
75 | # Directories potentially created on remote AFP share
76 | .AppleDB
77 | .AppleDesktop
78 | Network Trash Folder
79 | Temporary Items
80 | .apdisk
81 |
82 |
83 | ### Maven ###
84 | target/
85 | pom.xml.tag
86 | pom.xml.releaseBackup
87 | pom.xml.versionsBackup
88 | pom.xml.next
89 | release.properties
90 | dependency-reduced-pom.xml
91 | buildNumber.properties
92 |
93 |
94 | ### Java ###
95 | *.class
96 |
97 | # Mobile Tools for Java (J2ME)
98 | .mtj.tmp/
99 |
100 | # Package Files #
101 | *.jar
102 | *.war
103 | *.ear
104 |
105 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
106 | hs_err_pid*
107 |
108 | /extlib/
109 | /neo4j-home/
110 | nb-configuration.xml
111 | /data/
112 | .classpath
113 | .project
114 | .settings/
115 | neo4jextlib
116 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | before_install:
4 | - sudo apt-get update > /dev/null
5 |
6 | jdk:
7 | - oraclejdk8
8 | - oraclejdk7
9 |
10 | branches:
11 | only:
12 | - master
13 | - 2.2
14 |
15 | after_success:
16 | - echo "ossrh\${env.OSSRH_USER}\${env.OSSRH_PASS}" > ~/settings.xml
17 | - mvn deploy --settings ~/settings.xml
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | 4.0.0
21 |
22 | com.graphaware.es
23 | graph-aided-search
24 | 2.4.4.4-SNAPSHOT
25 |
26 |
27 | 1.7
28 | UTF-8
29 | 2.4.4
30 | 1.1.0-M04
31 | com.graphaware.es.gas.GraphAidedSearchPlugin
32 | 1.7
33 | 1.7
34 |
35 |
36 | Graph-Aided Search
37 | GraphAware Elasticsearch Plugin for Integration with Neo4j
38 | http://graphaware.com
39 |
40 |
41 |
42 | GNU General Public License, version 3
43 | http://www.gnu.org/licenses/gpl-3.0.txt
44 | repo
45 |
46 |
47 |
48 |
49 | Graph Aware Limited
50 | http://graphaware.com
51 |
52 |
53 |
54 | scm:git:git@github.com:graphaware/graph-aided-search.git
55 | scm:git:git@github.com:graphaware/graph-aided-search.git
56 | git@github.com:graphaware/graph-aided-search.git
57 | HEAD
58 |
59 |
60 |
61 |
62 | release
63 |
64 |
65 | performRelease
66 | true
67 |
68 |
69 |
70 |
71 |
72 | org.apache.maven.plugins
73 | maven-gpg-plugin
74 | 1.6
75 |
76 |
77 | sign-artifacts
78 | verify
79 |
80 | sign
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | doclint-java8-disable
90 |
91 | [1.8,)
92 |
93 |
94 |
95 |
96 |
97 | org.apache.maven.plugins
98 | maven-javadoc-plugin
99 |
100 | -Xdoclint:none
101 |
102 |
103 |
104 |
105 |
106 |
107 | intellij-javadoc-fix
108 |
109 |
110 |
111 | maven-javadoc-plugin
112 | 2.10.3
113 |
114 | ${java.home}/../bin/javadoc
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | alenegro
125 | Alessandro Negro
126 | alessandro@graphaware.com
127 |
128 |
129 | ikwattro
130 | Christophe Willemsen
131 | christophe@graphaware.com
132 |
133 |
134 | bachmanm
135 | Michal Bachman
136 | graph-aided-search@graphaware.com
137 |
138 |
139 |
140 |
141 | https://travis-ci.org/graphaware/graph-aided-search
142 | Travis CI
143 |
144 |
145 | 2015
146 |
147 |
148 | GitHub
149 | https://github.com/graphaware/graph-aided-search/issues
150 |
151 |
152 |
153 |
154 |
155 | org.elasticsearch
156 | elasticsearch
157 | ${elasticsearch.version}
158 | provided
159 |
160 |
161 |
162 | com.sun.jersey
163 | jersey-client
164 | 1.19
165 |
166 |
167 | com.sun.jersey
168 | jersey-json
169 | 1.19
170 |
171 |
172 | org.codehaus.jackson
173 | jackson-jaxrs
174 | 1.9.13
175 |
176 |
177 | com.google.guava
178 | guava
179 | 18.0
180 |
181 |
182 | org.reflections
183 | reflections
184 | 0.9.9
185 |
186 |
187 |
188 | javax.mail
189 | javax.mail-api
190 | 1.5.5
191 |
192 |
193 |
194 | org.neo4j.driver
195 | neo4j-java-driver
196 | ${bolt.version}
197 |
198 |
199 |
200 |
201 |
202 |
203 | org.codelibs
204 | elasticsearch-cluster-runner
205 | 2.3.0.0
206 | test
207 |
208 |
209 | junit
210 | junit
211 | 4.11
212 | test
213 |
214 |
215 | log4j
216 | log4j
217 | 1.2.17
218 | test
219 |
220 |
221 | io.searchbox
222 | jest
223 | 2.0.1
224 | test
225 |
226 |
227 | com.graphaware.integration.neo4j
228 | neo4j-tests-integration
229 | 3.0.6.1
230 | test
231 |
232 |
233 | org.apache.httpcomponents
234 | httpclient
235 | 4.5.1
236 | test
237 |
238 |
239 | org.springframework
240 | spring-core
241 | 4.2.3.RELEASE
242 | test
243 |
244 |
245 | org.mock-server
246 | mockserver-netty
247 | 3.10.4
248 | test
249 |
250 |
251 |
252 |
253 |
254 |
255 | org.apache.maven.plugins
256 | maven-release-plugin
257 | 2.5.3
258 |
259 | true
260 | false
261 | release
262 | deploy
263 |
264 |
265 |
266 | maven-assembly-plugin
267 | 2.6
268 |
269 | false
270 | ${project.build.directory}/releases/
271 |
272 | ${basedir}/src/main/assemblies/plugin.xml
273 |
274 |
275 |
276 |
277 | package
278 |
279 | single
280 |
281 |
282 |
283 |
284 |
285 | org.apache.maven.plugins
286 | maven-compiler-plugin
287 | 3.5.1
288 |
289 | ${java.version}
290 | ${java.version}
291 | ${project.build.sourceEncoding}
292 |
293 |
294 |
295 | org.apache.maven.plugins
296 | maven-deploy-plugin
297 | 2.8.2
298 |
299 | 10
300 |
301 |
302 |
303 | org.sonatype.plugins
304 | nexus-staging-maven-plugin
305 | 1.6.7
306 | true
307 |
308 | ossrh
309 | https://oss.sonatype.org/
310 | true
311 |
312 |
313 |
314 | org.apache.maven.plugins
315 | maven-source-plugin
316 | 3.0.0
317 |
318 |
319 | attach-sources
320 |
321 | jar-no-fork
322 |
323 |
324 |
325 |
326 |
327 | org.apache.maven.plugins
328 | maven-javadoc-plugin
329 | 2.10.3
330 |
331 | true
332 |
333 |
334 |
335 | attach-javadocs
336 |
337 | jar
338 |
339 |
340 |
341 | aggregate
342 |
343 | aggregate
344 |
345 | site
346 |
347 |
348 |
349 |
350 | maven-dependency-plugin
351 |
352 |
353 | copy-model
354 | compile
355 |
356 | copy
357 |
358 |
359 | true
360 | false
361 | true
362 |
363 |
364 | com.graphaware.integration.neo4j
365 | neo4j-tests-integration
366 | 3.0.6.1
367 | shaded
368 | true
369 |
370 |
371 | log4j
372 | log4j
373 | 1.2.17
374 | false
375 |
376 |
377 | com.sun.jersey
378 | jersey-core
379 | 1.19
380 |
381 |
382 | ${project.basedir}/neo4jextlib
383 |
384 |
385 |
386 |
387 |
388 | maven-clean-plugin
389 | 3.0.0
390 |
391 |
392 |
393 | ${project.basedir}/neo4jextlib
394 |
395 |
396 |
397 |
398 |
399 | org.apache.maven.plugins
400 | maven-surefire-plugin
401 | 2.19.1
402 |
403 | -Xmx2048m -XX:MaxPermSize=512m
404 |
405 | ${project.basedir}/neo4jextlib
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
--------------------------------------------------------------------------------
/src/main/assemblies/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | plugin
20 |
21 | zip
22 |
23 | false
24 |
25 |
26 | ${basedir}/src/main/plugin-metadata/plugin-descriptor.properties
27 |
28 | true
29 |
30 |
31 | ${basedir}/src/main/plugin-metadata/plugin-security.policy
32 |
33 | true
34 |
35 |
36 |
37 |
38 | /
39 | true
40 | true
41 |
42 | com.google.guava:guava
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/GraphAidedSearch.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Copyright (c) 2013-2016 GraphAware
4 | *
5 | * This file is part of the GraphAware Framework.
6 | *
7 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
8 | * the GNU General Public License as published by the Free Software Foundation, either
9 | * version 3 of the License, or (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 | * See the GNU General Public License for more details. You should have received a copy of
14 | * the GNU General Public License along with this program. If not, see
15 | * .
16 | */
17 | package com.graphaware.es.gas;
18 |
19 | import com.graphaware.es.gas.wrap.ActionListenerWrapper;
20 | import com.graphaware.es.gas.wrap.GraphAidedSearchActionListenerWrapper;
21 | import org.elasticsearch.action.support.ActionFilter;
22 | import org.elasticsearch.action.support.ActionFilters;
23 | import org.elasticsearch.client.Client;
24 | import org.elasticsearch.cluster.ClusterService;
25 | import org.elasticsearch.common.component.AbstractLifecycleComponent;
26 | import org.elasticsearch.common.inject.Inject;
27 | import org.elasticsearch.common.settings.Settings;
28 | import org.elasticsearch.script.ScriptService;
29 | import org.elasticsearch.threadpool.ThreadPool;
30 |
31 | public class GraphAidedSearch extends AbstractLifecycleComponent {
32 |
33 | private final ActionListenerWrapper> wrapper;
34 | private final ActionFilters filters;
35 |
36 | @Inject
37 | public GraphAidedSearch(final Settings settings, final Client client, final ClusterService clusterService, final ScriptService scriptService, final ThreadPool threadPool, final ActionFilters filters) {
38 | super(settings);
39 |
40 | this.filters = filters;
41 | this.wrapper = new GraphAidedSearchActionListenerWrapper(settings, clusterService, client);
42 |
43 | initializeFilters();
44 | }
45 |
46 | private void initializeFilters() {
47 | for (final ActionFilter filter : filters.filters()) {
48 | if (filter instanceof GraphAidedSearchFilter) {
49 | ((GraphAidedSearchFilter) filter).setWrapper(wrapper);
50 | if (logger.isDebugEnabled()) {
51 | logger.debug("Set GraphAidedSearch to " + filter);
52 | }
53 | }
54 | }
55 | }
56 |
57 | @Override
58 | protected void doStart() {
59 |
60 | }
61 |
62 | @Override
63 | protected void doStop() {
64 |
65 | }
66 |
67 | @Override
68 | protected void doClose() {
69 |
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/GraphAidedSearchFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas;
17 |
18 | import com.graphaware.es.gas.wrap.ActionListenerWrapper;
19 | import com.graphaware.es.gas.wrap.CannotWrapException;
20 | import org.elasticsearch.action.ActionListener;
21 | import org.elasticsearch.action.ActionRequest;
22 | import org.elasticsearch.action.ActionResponse;
23 | import org.elasticsearch.action.search.SearchAction;
24 | import org.elasticsearch.action.search.SearchRequest;
25 | import org.elasticsearch.action.support.ActionFilter;
26 | import org.elasticsearch.action.support.ActionFilterChain;
27 | import org.elasticsearch.common.component.AbstractComponent;
28 | import org.elasticsearch.common.inject.Inject;
29 | import org.elasticsearch.common.logging.ESLogger;
30 | import org.elasticsearch.common.logging.Loggers;
31 | import org.elasticsearch.common.settings.Settings;
32 | import org.elasticsearch.tasks.Task;
33 |
34 | public class GraphAidedSearchFilter extends AbstractComponent implements ActionFilter {
35 |
36 | private static final int DEFAULT_FILTER_ORDER = 10;
37 |
38 | private static final String FILTER_ORDER_KEY_NAME = "indices.graphaware.filter.order";
39 |
40 | protected final ESLogger logger;
41 |
42 | private final int order;
43 |
44 | private ActionListenerWrapper> wrapper;
45 |
46 | @Inject
47 | public GraphAidedSearchFilter(final Settings settings) {
48 | super(settings);
49 | logger = Loggers.getLogger(GraphAidedSearchFilter.class.getName(), settings);
50 | order = settings.getAsInt(FILTER_ORDER_KEY_NAME, DEFAULT_FILTER_ORDER);
51 | }
52 |
53 | public void setWrapper(ActionListenerWrapper> wrapper) {
54 | this.wrapper = wrapper;
55 | }
56 |
57 | @Override
58 | public int order() {
59 | return order;
60 | }
61 |
62 | @Override
63 | public void apply(Task task, String action, ActionRequest request, ActionListener listener, ActionFilterChain chain) {
64 | if (SearchAction.INSTANCE.name().equals(action)) {
65 | try {
66 | listener = wrapper.wrap((SearchRequest) request, listener);
67 | } catch (CannotWrapException e) {
68 | //that's OK, will use the original unwrapped one and perform no Graph-Aided Search
69 | }
70 | }
71 |
72 | chain.proceed(task, action, request, listener);
73 | }
74 |
75 | @Override
76 | public void apply(final String action, final ActionResponse response, final ActionListener listener, final ActionFilterChain chain) {
77 | chain.proceed(action, response, listener);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/GraphAidedSearchModule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas;
17 |
18 | import org.elasticsearch.common.inject.AbstractModule;
19 |
20 | public class GraphAidedSearchModule extends AbstractModule {
21 |
22 | @Override
23 | protected void configure() {
24 | bind(GraphAidedSearch.class).asEagerSingleton();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/GraphAidedSearchPlugin.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas;
17 |
18 | import org.elasticsearch.action.ActionModule;
19 | import org.elasticsearch.cluster.ClusterModule;
20 | import org.elasticsearch.cluster.settings.Validator;
21 | import org.elasticsearch.common.inject.Module;
22 | import org.elasticsearch.plugins.Plugin;
23 |
24 | import java.util.Collection;
25 | import java.util.Collections;
26 |
27 | import static com.graphaware.es.gas.wrap.GraphAidedSearchActionListenerWrapper.*;
28 |
29 | public class GraphAidedSearchPlugin extends Plugin {
30 |
31 | @Override
32 | public String name() {
33 | return "GraphAidedSearchPlugin";
34 | }
35 |
36 | @Override
37 | public String description() {
38 | return "GraphAware Graph-Aided Search Plugin for Neo4j.";
39 | }
40 |
41 | public void onModule(final ActionModule module) {
42 | module.registerFilter(GraphAidedSearchFilter.class);
43 | }
44 |
45 | public void onModule(final ClusterModule module) {
46 | module.registerIndexDynamicSetting(INDEX_GA_ES_NEO4J_ENABLED, Validator.BOOLEAN);
47 | module.registerIndexDynamicSetting(INDEX_GA_ES_NEO4J_HOST, Validator.EMPTY);
48 | module.registerIndexDynamicSetting(INDEX_GA_ES_NEO4J_USER, Validator.EMPTY);
49 | module.registerIndexDynamicSetting(INDEX_GA_ES_NEO4J_PWD, Validator.EMPTY);
50 | }
51 |
52 | @Override
53 | public Collection nodeModules() {
54 | return Collections.singleton(new GraphAidedSearchModule());
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/annotation/SearchBooster.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.annotation;
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 | import java.lang.annotation.Target;
22 |
23 | @Retention(RetentionPolicy.RUNTIME)
24 | @Target(ElementType.TYPE)
25 | public @interface SearchBooster {
26 |
27 | String name();
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/annotation/SearchFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.annotation;
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 | import java.lang.annotation.Target;
22 |
23 | @Retention(RetentionPolicy.RUNTIME)
24 | @Target(ElementType.TYPE)
25 | public @interface SearchFilter {
26 |
27 | String name();
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/booster/SearchResultBooster.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.booster;
17 |
18 | import com.graphaware.es.gas.modifier.SearchResultModifier;
19 |
20 | public interface SearchResultBooster extends SearchResultModifier {
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/booster/SearchResultCypherBooster.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.booster;
17 |
18 | import com.graphaware.es.gas.annotation.SearchBooster;
19 | import com.graphaware.es.gas.cypher.CypherEndPoint;
20 | import com.graphaware.es.gas.cypher.CypherEndPointBuilder;
21 | import com.graphaware.es.gas.cypher.CypherResult;
22 | import com.graphaware.es.gas.cypher.ResultRow;
23 | import com.graphaware.es.gas.domain.ExternalResult;
24 | import com.graphaware.es.gas.domain.IndexInfo;
25 | import com.graphaware.es.gas.util.NumberUtil;
26 | import com.graphaware.es.gas.util.UrlUtil;
27 | import org.elasticsearch.common.logging.ESLogger;
28 | import org.elasticsearch.common.logging.Loggers;
29 | import org.elasticsearch.common.settings.Settings;
30 |
31 | import java.util.HashMap;
32 | import java.util.Map;
33 | import java.util.Set;
34 |
35 | import static com.graphaware.es.gas.domain.ClauseConstants.*;
36 | import static com.graphaware.es.gas.util.ParamUtil.extractParameter;
37 |
38 | @SearchBooster(name = "SearchResultCypherBooster")
39 | public class SearchResultCypherBooster extends SearchResultExternalBooster {
40 |
41 | private final ESLogger logger;
42 | private CypherEndPoint cypherEndPoint;
43 |
44 | private String cypherQuery;
45 | private String scoreResultName;
46 | private String idResultName;
47 |
48 | public SearchResultCypherBooster(Settings settings, IndexInfo indexInfo) {
49 | super(settings, indexInfo);
50 | this.logger = Loggers.getLogger(IndexInfo.INDEX_LOGGER_NAME, settings);
51 | }
52 |
53 | @Override
54 | protected void extendedParseRequest(Map extParams) {
55 | cypherQuery = extractParameter(QUERY, extParams);
56 | scoreResultName = extractParameter(SCORE_NAME, extParams, DEFAULT_SCORE_RESULT_NAME);
57 | idResultName = extractParameter(IDENTIFIER, extParams, DEFAULT_ID_RESULT_NAME);
58 | String protocol = extParams.containsKey(PROTOCOL) ? String.valueOf(extParams.get(PROTOCOL)) : DEFAULT_PROTOCOL;
59 | cypherEndPoint = createCypherEndPoint(protocol, getSettings());
60 | }
61 |
62 | @Override
63 | protected Map externalDoReorder(Set keySet) {
64 | logger.debug("Query cypher for: " + keySet);
65 | return getExternalResults(keySet);
66 | }
67 |
68 | protected Map getExternalResults(Set keySet) {
69 | CypherResult externalResult = cypherEndPoint.executeCypher(cypherQuery, getParameters(keySet));
70 | Map results = new HashMap<>();
71 | for (ResultRow resultRow : externalResult.getRows()) {
72 | checkResultRow(resultRow);
73 | results.put(String.valueOf(resultRow.get(getIdResultName())), new ExternalResult(String.valueOf(resultRow.get(getIdResultName())), NumberUtil.getFloat(resultRow.get(getScoreResultName()))));
74 | }
75 |
76 | return results;
77 | }
78 |
79 | public HashMap getParameters(Set resultKeySet) {
80 | HashMap parameters = new HashMap<>();
81 | parameters.put("ids", resultKeySet);
82 |
83 | return parameters;
84 | }
85 |
86 | public String getEndpoint(String serverUrl) {
87 | return UrlUtil.buildUrlFromParts(serverUrl);
88 | }
89 |
90 | public String getScoreResultName() {
91 | return null != scoreResultName ? scoreResultName : DEFAULT_SCORE_RESULT_NAME;
92 | }
93 |
94 | public String getIdResultName() {
95 | return null != idResultName ? idResultName : DEFAULT_ID_RESULT_NAME;
96 | }
97 |
98 | protected void checkResultRow(ResultRow resultRow) {
99 | if (!resultRow.getValues().containsKey(getIdResultName())) {
100 | dispatchInvalidResultException(getIdResultName());
101 | }
102 | if (!resultRow.getValues().containsKey(getScoreResultName())) {
103 | dispatchInvalidResultException(getScoreResultName());
104 | }
105 | }
106 |
107 | private void dispatchInvalidResultException(String missingKey) {
108 | throw new RuntimeException(String.format("The cypher query result must contain the %s column name", missingKey));
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/booster/SearchResultExternalBooster.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.booster;
17 |
18 | import com.graphaware.es.gas.cypher.CypherSettingsReader;
19 | import com.graphaware.es.gas.domain.ExternalResult;
20 | import com.graphaware.es.gas.domain.IndexInfo;
21 | import com.graphaware.es.gas.util.NumberUtil;
22 | import org.elasticsearch.common.settings.Settings;
23 | import org.elasticsearch.search.internal.InternalSearchHit;
24 | import org.elasticsearch.search.internal.InternalSearchHits;
25 |
26 | import java.util.*;
27 |
28 | import static com.graphaware.es.gas.domain.ClauseConstants.*;
29 | import static com.graphaware.es.gas.util.ParamUtil.*;
30 | import static com.graphaware.es.gas.wrap.GraphAidedSearchActionListenerWrapper.*;
31 |
32 | public abstract class SearchResultExternalBooster extends CypherSettingsReader implements SearchResultBooster {
33 |
34 | protected static final String DEFAULT_SCORE_OPERATOR = MULTIPLY;
35 | protected static final String DEFAULT_PROTOCOL = "http";
36 | static final String DEFAULT_SCORE_RESULT_NAME = "score";
37 | static final String DEFAULT_ID_RESULT_NAME = "id";
38 |
39 |
40 | private int maxResultSize = -1;
41 |
42 | private int size;
43 | private int from;
44 |
45 | protected String composeScoreOperator;
46 |
47 | public SearchResultExternalBooster(Settings settings, IndexInfo indexSettings) {
48 | super(settings, indexSettings);
49 | }
50 |
51 | @Override
52 | public final void parseRequest(Map sourceAsMap) {
53 | size = NumberUtil.getInt(sourceAsMap.get(SIZE), 10);
54 | from = NumberUtil.getInt(sourceAsMap.get(FROM), 0);
55 |
56 | Map extParams = (Map) sourceAsMap.get(GAS_BOOSTER_CLAUSE);
57 | if (extParams != null) {
58 | maxResultSize = NumberUtil.getInt(extParams.get(MAX_RESULT_SIZE), getMaxResultWindow());
59 | composeScoreOperator = extractParameter(OPERATOR, extParams, DEFAULT_SCORE_OPERATOR);
60 | extendedParseRequest(extParams);
61 | validateOperator();
62 | }
63 | if (maxResultSize > 0) {
64 | sourceAsMap.put(SIZE, maxResultSize);
65 | }
66 | sourceAsMap.put(FROM, 0);
67 | }
68 |
69 | @Override
70 | public InternalSearchHits modify(final InternalSearchHits hits) {
71 | final InternalSearchHit[] searchHits = hits.internalHits();
72 | Map hitMap = new HashMap<>();
73 | for (InternalSearchHit hit : searchHits) {
74 | hitMap.put(hit.getId(), hit);
75 | }
76 | int totalHitsSize = hitMap.keySet().size();
77 | Map remoteScore = externalDoReorder(hitMap.keySet());
78 | final int arraySize = (size + from) < searchHits.length ? size
79 | : (searchHits.length - from) > 0 ? (searchHits.length - from) : 0;
80 | if (arraySize == 0) {
81 | return new InternalSearchHits(new InternalSearchHit[0], 0, 0);
82 | }
83 |
84 | final int totalSize = arraySize + from;
85 | List newSearchHits = new ArrayList<>(totalSize);
86 | float maxScore = -1;
87 | for (Map.Entry item : hitMap.entrySet()) {
88 | ExternalResult remoteResult = remoteScore.get(item.getKey());
89 | if (remoteResult != null) {
90 | float newScore = composeScore(item.getValue().score(), remoteResult.getScore());
91 | if (maxScore < newScore) {
92 | maxScore = newScore;
93 | }
94 | item.getValue().score(newScore);
95 | }
96 | int k = 0;
97 | while (newSearchHits.size() > 0
98 | && k < newSearchHits.size()
99 | && newSearchHits.get(k) != null
100 | && newSearchHits.get(k).score() > item.getValue().score()
101 | && k < totalSize) {
102 | k++;
103 | }
104 | if (k < totalSize) {
105 | newSearchHits.add(k, item.getValue());
106 | }
107 | if (newSearchHits.size() > totalSize) {
108 | newSearchHits.remove(totalSize);
109 | }
110 | }
111 | if (from > 0) {
112 | int k = 0;
113 | while (k < from) {
114 | newSearchHits.remove(0);
115 | k++;
116 | }
117 | }
118 | return new InternalSearchHits(newSearchHits.toArray(new InternalSearchHit[arraySize]), totalHitsSize,
119 | maxScore);
120 | }
121 |
122 | protected float composeScore(float esScore, float extScore) {
123 | switch (getComposeScoreOperator()) {
124 | case MULTIPLY:
125 | return esScore * extScore;
126 | case DIVIDE:
127 | return esScore / extScore;
128 | case PLUS:
129 | return esScore + extScore;
130 | case MINUS:
131 | return esScore - extScore;
132 | case REPLACE:
133 | return extScore;
134 | default:
135 | return esScore;
136 | }
137 |
138 | }
139 |
140 | public int getSize() {
141 | return size;
142 | }
143 |
144 | public int getFrom() {
145 | return from;
146 | }
147 |
148 | public int getMaxResultSize() {
149 | return maxResultSize;
150 | }
151 |
152 | protected abstract Map externalDoReorder(Set keySet);
153 |
154 | protected void extendedParseRequest(Map extParams) {
155 |
156 | }
157 |
158 | protected void validateOperator() {
159 | Set validOperators = new HashSet<>();
160 | validOperators.add(MULTIPLY);
161 | validOperators.add(PLUS);
162 | validOperators.add(MINUS);
163 | validOperators.add(DIVIDE);
164 | validOperators.add(REPLACE);
165 |
166 | String operator = getComposeScoreOperator();
167 |
168 | if (!validOperators.contains(operator)) {
169 | throw new IllegalArgumentException("Operator \"" + operator + "\" is not valid");
170 | }
171 | }
172 |
173 | protected String getComposeScoreOperator() {
174 | return composeScoreOperator != null ? composeScoreOperator : DEFAULT_SCORE_OPERATOR;
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/booster/SearchResultNeo4jBooster.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.booster;
17 |
18 | import com.graphaware.es.gas.annotation.SearchBooster;
19 | import com.graphaware.es.gas.domain.ExternalResult;
20 | import com.graphaware.es.gas.domain.IndexInfo;
21 | import com.graphaware.es.gas.util.UrlUtil;
22 | import com.sun.jersey.api.client.Client;
23 | import com.sun.jersey.api.client.ClientResponse;
24 | import com.sun.jersey.api.client.GenericType;
25 | import com.sun.jersey.api.client.WebResource;
26 | import com.sun.jersey.api.client.config.ClientConfig;
27 | import com.sun.jersey.api.client.config.DefaultClientConfig;
28 | import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
29 | import org.elasticsearch.common.logging.ESLogger;
30 | import org.elasticsearch.common.logging.Loggers;
31 | import org.elasticsearch.common.settings.Settings;
32 |
33 | import javax.ws.rs.core.MediaType;
34 | import java.util.HashMap;
35 | import java.util.List;
36 | import java.util.Map;
37 | import java.util.Set;
38 |
39 | import com.sun.jersey.api.client.ClientHandlerException;
40 | import com.sun.jersey.api.client.UniformInterfaceException;
41 | import com.sun.jersey.core.util.MultivaluedMapImpl;
42 | import javax.ws.rs.core.HttpHeaders;
43 | import javax.ws.rs.core.MultivaluedMap;
44 |
45 | import static com.graphaware.es.gas.domain.ClauseConstants.*;
46 |
47 | @SearchBooster(name = "SearchResultNeo4jBooster")
48 | public class SearchResultNeo4jBooster extends SearchResultExternalBooster {
49 |
50 | private static final String DEFAULT_KEY_PROPERTY = "uuid";
51 | private static final String DEFAULT_REST_ENDPOINT = "/graphaware/recommendation/filter";
52 |
53 | private String boosterEndpoint = null;
54 | private final ESLogger logger;
55 | private String targetId;
56 | private String keyProperty;
57 |
58 | public SearchResultNeo4jBooster(Settings settings, IndexInfo indexSettings) {
59 | super(settings, indexSettings);
60 | this.logger = Loggers.getLogger(IndexInfo.INDEX_LOGGER_NAME, settings);
61 | }
62 |
63 | @Override
64 | protected Map externalDoReorder(Set keySet) {
65 | if (logger.isDebugEnabled()) {
66 | logger.debug("External Neo4j booster for : " + keySet);
67 | logger.debug("Call: " + getEndpoint());
68 | }
69 | return getReorderedResults(getExternalResults(keySet));
70 |
71 | }
72 |
73 | public Map getReorderedResults(List externalResults) {
74 | HashMap results = new HashMap<>();
75 | for (ExternalResult item : externalResults) {
76 | results.put(item.getObjectId(), item);
77 | }
78 |
79 | return results;
80 | }
81 |
82 | public List getExternalResults(Set keySet) {
83 |
84 | ClientConfig cfg = new DefaultClientConfig();
85 | cfg.getClasses().add(JacksonJsonProvider.class);
86 | WebResource resource = Client.create(cfg).resource(getEndpoint());
87 | WebResource.Builder resBuilder = resource.accept(MediaType.APPLICATION_JSON);
88 | setHeader(resBuilder);
89 | ClientResponse response = null;
90 | List externalResults = null;
91 |
92 | try {
93 | response = resBuilder.post(ClientResponse.class, getParameters(keySet));
94 | GenericType> type = new GenericType>() {
95 | };
96 | externalResults = response.getEntity(type);
97 | }
98 | catch (UniformInterfaceException | ClientHandlerException ex) {
99 | throw new RuntimeException("Error while connecting to neo4j host", ex);
100 | }
101 | finally {
102 | if (response != null)
103 | response.close();
104 | }
105 | if (externalResults == null) {
106 | logger.error("Null results from neo4j endpoint");
107 | throw new RuntimeException("Null results from neo4j endpoint. No results returned");
108 | }
109 | return externalResults;
110 | }
111 |
112 | private void setHeader(WebResource.Builder resBuilder) {
113 | Map headers = new HashMap<>();
114 | if (null != getNeo4jPassword()) {
115 | headers.put(HttpHeaders.AUTHORIZATION, UrlUtil.getAuthorizationHeaderValue(getNeo4jUsername(), getNeo4jPassword()));
116 | }
117 | for (String k : headers.keySet()) {
118 | resBuilder.header(k, headers.get(k));
119 | }
120 | }
121 |
122 | @Override
123 | protected void extendedParseRequest(Map extParams) {
124 | targetId = extParams.get(TARGET);
125 | keyProperty = extParams.get(KEY_PROPERTY) != null ? extParams.get(KEY_PROPERTY) : DEFAULT_KEY_PROPERTY;
126 | boosterEndpoint = extParams.get(NEO4J_ENDPOINT);
127 | }
128 |
129 | public MultivaluedMap getParameters(Set keySet) {
130 | MultivaluedMap param = new MultivaluedMapImpl();
131 | param.add("limit", String.valueOf(Integer.MAX_VALUE));
132 | param.add("from", String.valueOf(getFrom()));
133 | param.add("keyProperty", getKeyProperty());
134 | param.add("ids", implodeKeySet(keySet));
135 | return param;
136 | }
137 |
138 | protected String getTargetId() {
139 | return targetId;
140 | }
141 |
142 | public String getKeyProperty() {
143 | return keyProperty;
144 | }
145 |
146 | public String getEndpoint() {
147 | String boosterUrl = null != boosterEndpoint ? boosterEndpoint : DEFAULT_REST_ENDPOINT;
148 |
149 | return UrlUtil.buildUrlFromParts(getNeo4jHost(), boosterUrl, targetId);
150 | }
151 |
152 | public String implodeKeySet(Set keySet) {
153 | boolean isFirst = true;
154 | String ids = "";
155 | for (String id : keySet) {
156 | if (!isFirst) {
157 | ids = ids.concat(",");
158 | }
159 | isFirst = false;
160 | ids = ids.concat(id);
161 | }
162 |
163 | return ids;
164 | }
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/cypher/CypherBoltHttpEndPoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.cypher;
17 |
18 | import java.util.HashMap;
19 |
20 | import org.elasticsearch.common.settings.Settings;
21 | import org.neo4j.driver.v1.AuthTokens;
22 | import org.neo4j.driver.v1.Config;
23 | import static org.neo4j.driver.v1.Config.EncryptionLevel.NONE;
24 | import org.neo4j.driver.v1.Driver;
25 | import org.neo4j.driver.v1.GraphDatabase;
26 | import org.neo4j.driver.v1.Record;
27 | import org.neo4j.driver.v1.Session;
28 | import org.neo4j.driver.v1.StatementResult;
29 | import org.neo4j.driver.v1.Value;
30 | import org.neo4j.driver.v1.util.Pair;
31 |
32 | public class CypherBoltHttpEndPoint extends CypherEndPoint {
33 |
34 | private boolean encryption = true;
35 |
36 | CypherBoltHttpEndPoint(Settings settings, String neo4jUrl, String neo4jUsername, String neo4jPassword, boolean encryption) {
37 | super(settings, neo4jUrl, neo4jUsername, neo4jPassword);
38 | this.encryption = encryption;
39 | }
40 |
41 | public CypherResult executeCypher(String cypherQuery) {
42 | return executeCypher(cypherQuery, new HashMap());
43 | }
44 |
45 | @Override
46 | public CypherResult executeCypher(String cypherQuery, HashMap parameters) {
47 | try {
48 | Driver driver;
49 | if (encryption) {
50 | if (getNeo4jUsername() != null) {
51 | driver = GraphDatabase.driver(getNeo4jHost(), AuthTokens.basic(getNeo4jUsername(), getNeo4jPassword()));
52 | } else {
53 | driver = GraphDatabase.driver(getNeo4jHost());
54 | }
55 | } else {
56 | if (getNeo4jUsername() != null) {
57 | driver = GraphDatabase.driver(getNeo4jHost(), AuthTokens.basic(getNeo4jUsername(), getNeo4jPassword()), Config.build().withEncryptionLevel(NONE).toConfig());
58 | } else {
59 | driver = GraphDatabase.driver(getNeo4jHost(), Config.build().withEncryptionLevel(NONE).toConfig());
60 | }
61 | }
62 | Session session = driver.session();
63 | StatementResult response = session.run(cypherQuery, parameters);
64 | return buildResult(response);
65 | } catch (Exception ex) {
66 | throw new RuntimeException(ex);
67 | }
68 | }
69 |
70 | private CypherResult buildResult(StatementResult response) {
71 | CypherResult result = new CypherResult();
72 | while (response.hasNext()) {
73 | Record record = response.next();
74 | ResultRow resultRow = new ResultRow();
75 | for (Pair fieldInRecord : record.fields()) {
76 | resultRow.add(fieldInRecord.key(), fieldInRecord.value());
77 | }
78 | result.addRow(resultRow);
79 | }
80 | return result;
81 | }
82 |
83 | @Override
84 | public CypherResult executeCypher(HashMap headers, String query, HashMap parameters) {
85 | return executeCypher(query, parameters);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/cypher/CypherEndPoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.cypher;
17 |
18 | import com.graphaware.es.gas.domain.IndexInfo;
19 | import java.util.HashMap;
20 | import org.elasticsearch.common.logging.ESLogger;
21 | import org.elasticsearch.common.logging.Loggers;
22 | import org.elasticsearch.common.settings.Settings;
23 |
24 | public abstract class CypherEndPoint {
25 |
26 | protected final ESLogger logger;
27 | private final String neo4jHost;
28 | private final String neo4jPassword;
29 | private final String neo4jUsername;
30 |
31 |
32 | public CypherEndPoint(Settings settings, String neo4jHost) {
33 | this(settings, neo4jHost, null, null);
34 | }
35 |
36 | public CypherEndPoint(Settings settings, String neo4jHost, String neo4jUsername, String neo4jPassword) {
37 | this.neo4jHost = neo4jHost;
38 | this.neo4jUsername = neo4jUsername;
39 | this.neo4jPassword = neo4jPassword;
40 | if (settings != null) {
41 | this.logger = Loggers.getLogger(IndexInfo.INDEX_LOGGER_NAME, settings);
42 | } else {
43 | this.logger = Loggers.getLogger(IndexInfo.INDEX_LOGGER_NAME, Settings.EMPTY);
44 | }
45 | }
46 |
47 | public String getNeo4jPassword() {
48 | return neo4jPassword;
49 | }
50 |
51 | public String getNeo4jUsername() {
52 | return neo4jUsername;
53 | }
54 |
55 | public String getNeo4jHost() {
56 | return neo4jHost;
57 | }
58 |
59 | public abstract CypherResult executeCypher(String query, HashMap parameters);
60 |
61 | public abstract CypherResult executeCypher(HashMap headers, String query, HashMap parameters);
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/cypher/CypherEndPointBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.cypher;
17 |
18 | import org.elasticsearch.common.settings.Settings;
19 |
20 | public class CypherEndPointBuilder {
21 |
22 | private Settings settings;
23 | private String neo4jHost;
24 | private String neo4jBoltHost;
25 | private final CypherEndPointType protocol;
26 | private String neo4jUsername;
27 | private String neo4jPassword;
28 | private boolean encryption = true;
29 |
30 | public CypherEndPointBuilder(CypherEndPointType protocol) {
31 | this.protocol = protocol;
32 | }
33 |
34 | public CypherEndPointBuilder(String protocol) {
35 | this.protocol = CypherEndPointType.getEnum(protocol);
36 | }
37 |
38 |
39 | public CypherEndPointBuilder settings(Settings settings) {
40 | this.settings = settings;
41 | return this;
42 | }
43 |
44 | public CypherEndPointBuilder neo4jHostname(String neo4jHost) {
45 | this.neo4jHost = neo4jHost;
46 | return this;
47 | }
48 |
49 | public CypherEndPointBuilder neo4jBoltHostname(String neo4jBoltHost) {
50 | this.neo4jBoltHost = neo4jBoltHost;
51 | return this;
52 | }
53 |
54 | public CypherEndPointBuilder username(String neo4jUsername) {
55 | this.neo4jUsername = neo4jUsername;
56 | return this;
57 | }
58 |
59 | public CypherEndPointBuilder password(String neo4jPassword) {
60 | this.neo4jPassword = neo4jPassword;
61 | return this;
62 | }
63 |
64 | public CypherEndPointBuilder encryption(boolean encryption) {
65 | this.encryption = encryption;
66 | return this;
67 | }
68 |
69 | public CypherEndPoint build() {
70 | checkNeo4jHost();
71 | switch (protocol) {
72 | case HTTP:
73 | return new CypherHttpEndPoint(settings,
74 | neo4jHost,
75 | neo4jUsername,
76 | neo4jPassword
77 | );
78 | case BOLT:
79 | return new CypherBoltHttpEndPoint(settings,
80 | neo4jBoltHost,
81 | neo4jUsername,
82 | neo4jPassword,
83 | encryption);
84 | }
85 | throw new RuntimeException("Type " + protocol + " not supported");
86 | }
87 |
88 | private void checkNeo4jHost() {
89 | if (neo4jHost == null)
90 | throw new RuntimeException("No neo4j hosts specified for http connection in the index settings");
91 | }
92 |
93 | public enum CypherEndPointType {
94 | HTTP("http"),
95 | BOLT("bolt");
96 |
97 | String name;
98 |
99 | CypherEndPointType(String name) {
100 | this.name = name;
101 | }
102 |
103 | public String getName() {
104 | return name;
105 | }
106 |
107 | public static CypherEndPointType getEnum(String value) {
108 | if (HTTP.getName().equalsIgnoreCase(value)) {
109 | return HTTP;
110 | } else if (BOLT.getName().equalsIgnoreCase(value)) {
111 | return BOLT;
112 | }
113 | throw new RuntimeException("Type " + value + " not supported");
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/es/gas/cypher/CypherHttpEndPoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
7 | * the GNU General Public License as published by the Free Software Foundation, either
8 | * version 3 of the License, or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of
13 | * the GNU General Public License along with this program. If not, see
14 | * .
15 | */
16 | package com.graphaware.es.gas.cypher;
17 |
18 | import com.graphaware.es.gas.util.UrlUtil;
19 | import com.sun.jersey.api.client.Client;
20 | import com.sun.jersey.api.client.ClientResponse;
21 | import com.sun.jersey.api.client.GenericType;
22 | import com.sun.jersey.api.client.WebResource;
23 | import com.sun.jersey.api.client.config.ClientConfig;
24 | import com.sun.jersey.api.client.config.DefaultClientConfig;
25 | import java.io.IOException;
26 | import java.util.HashMap;
27 | import java.util.List;
28 | import java.util.Map;
29 | import javax.ws.rs.core.HttpHeaders;
30 | import javax.ws.rs.core.MediaType;
31 | import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
32 | import org.codehaus.jackson.map.ObjectMapper;
33 | import org.elasticsearch.common.settings.Settings;
34 |
35 | public class CypherHttpEndPoint extends CypherEndPoint {
36 |
37 | private static final String CYPHER_ENDPOINT = "/db/data/transaction/commit";
38 | private static final String CYPHER_RESPONSE_RESULTS_FIELD = "results";
39 | private static final String CYPHER_RESPONSE_DATA_FIELD = "data";
40 | private static final String CYPHER_RESPONSE_COLUMNS_FIELD = "columns";
41 | private static final String CYPHER_RESPONSE_ERRORS_FIELD = "errors";
42 | private static final String CYPHER_RESPONSE_ROW_FIELD = "row";
43 |
44 | private final ClientConfig cfg;
45 | private final StringBuilder stringBuilder;
46 | private final ObjectMapper mapper;
47 |
48 | public CypherHttpEndPoint(Settings settings, String neo4jUrl, String neo4jUsername, String neo4jPassword) {
49 | super(settings, neo4jUrl, neo4jUsername, neo4jPassword);
50 | cfg = new DefaultClientConfig();
51 | cfg.getClasses().add(JacksonJsonProvider.class);
52 | stringBuilder = new StringBuilder();
53 | mapper = new ObjectMapper();
54 | }
55 |
56 | public String buildCypherQuery(String cypherQuery) {
57 | return buildCypherQuery(cypherQuery, new HashMap());
58 | }
59 |
60 | @Override
61 | public CypherResult executeCypher(String query, HashMap parameters) {
62 | HashMap headers = new HashMap<>();
63 |
64 | return executeCypher(headers, query, parameters);
65 | }
66 |
67 | @Override
68 | public CypherResult executeCypher(HashMap headers, String query, HashMap parameters) {
69 | String jsonBody = buildCypherQuery(query, parameters);
70 | String cypherEndpoint = UrlUtil.buildUrlFromParts(getNeo4jHost(), CYPHER_ENDPOINT);
71 | Map response = post(cypherEndpoint, headers, jsonBody);
72 | checkErrors(response);
73 |
74 | return buildCypherResult(response);
75 | }
76 |
77 | public CypherResult buildCypherResult(Map response) {
78 | Map res = (Map) ((List) response.get(CYPHER_RESPONSE_RESULTS_FIELD)).get(0);
79 | List