使用Neo4j和Elasticsearch实现互操作.
首先
我想要使用Elasticsearch对存储在Neo4j中的数据进行全文搜索。
我在以下环境中进行了测试:
– Windows10 Home
– Neo4j社区版3.5.5
– Elasticsearch 6.6.2
调查
似乎有一些插件。
· neo4j-elasticsearch
这是Neo4j官方提供的插件。
目前仅支持2.2.x,2.3.x,3.0.x和3.1.x版本。
无法在最新版本中使用。
★GraphAware Neo4j-To-Elasticsearch
GraphAware在为Neo4j开发的插件。
可以自动将Neo4j的数据复制到ElasticSearch中。
技术支持需要付费。
・GraphAware图搜索插件
GraphAware公司开发的ElasticSearch插件。
可以在ElasticSearch中搜索Neo4j内的数据。
可以在ElasticSearch的搜索查询中对Neo4j数据进行评分和筛选。
还可以使用Cypher进行评分。
支持需要付费。
这次我尝试了neo4j-to-elasticsearch。
Neo4j对Elasticsearch 进行整合
按照Readme上的指示进行。
首先从这里或这里开始搜索并下载以下三个.jar文件。(目前最新版本为3.5.4.53)
– GraphAware Neo4j Framework
– GraphAware Neo4j UUID
– GraphAware Neo4j Elasticsearch Integration
将下载的.jar文件复制到$NEO4J_HOME/plugins目录中。
在$NEO4J_HOME/conf/neo4j.conf文件中添加以下内容
# おまじない
dbms.unmanaged_extension_classes=com.graphaware.server=/graphaware
com.graphaware.runtime.enabled=true
com.graphaware.module.UIDM.1=com.graphaware.module.uuid.UuidBootstrapper
com.graphaware.module.UIDM.initializeUntil=0
# おまじない
com.graphaware.module.ES.2=com.graphaware.module.es.ElasticSearchModuleBootstrapper
# Elasticsearchのuriとポート
com.graphaware.module.ES.uri=localhost
com.graphaware.module.ES.port=9200
# キューのサイズ。メモリ不足でエラーが出る場合は小さくする
com.graphaware.module.ES.queueSize=10000
# Elasticsearchのbulk APIを使うかどうか。メモリ不足でエラーが出る場合はfalseにしてみる
com.graphaware.module.ES.bulk=true
# System.currentTimeMillis() < initializeUntil にしてNeo4jを起動するとDB全体をインデックスしなおしてくれる
# 普段は0にして、色々いじってるときは2000000000000ぐらいにするといい
com.graphaware.module.ES.initializeUntil=2000000000000
# インデックスするノードの条件。trueだと全ノード。hasLabel("Person")||hasLabel("Company")のように設定できる
com.graphaware.module.ES.node=true
# 後で説明する
# com.graphaware.module.ES.mapping=com.graphaware.module.es.mapping.JsonFileMapping
# com.graphaware.module.ES.file=mapping.json
这样先能够正常运行。
启动Neo4j后,节点和关系应该会被索引到Elasticsearch中。
(顺便提一下,建议使用neo4j console而不是neo4j start,这样可以看到错误信息)
之后,更新的节点也会自动被索引。
使用Kibana进行确认。
GET neo4j-index-node/_search
{
"query": {
"match_all": {}
}
}
GET neo4j-index-relationship/_search
{
"query": {
"match_all": {}
}
}
在 Elasticsearch 5.x 版本之前,可能不会出现任何问题,但在 Elasticsearch 6.x 版本中,仅仅这样做是无法正常工作的。
如果使用Elasticsearch 6.x或更高的版本
如果使用Elasticsearch 6.x版本,会发现除最初索引的标签外,其他标签不会被索引。这是因为Elasticsearch 6.x不再支持在索引内设置多个类型。由于Neo4j-To-Elasticsearch默认创建每个标签的类型在索引内,所以会发生错误。
用JsonFileMapping来处理。
可以在附加的配置文件中指定 Neo4j 属性到 Elasticsearch 属性的映射,关于具体细节,请参考此处。
在neo4j.conf中添加之前被注释掉的行。
com.graphaware.module.ES.mapping=com.graphaware.module.es.mapping.JsonFileMapping
com.graphaware.module.ES.file=mapping.json
在与neo4j.conf相同的目录中创建一个新的mapping.json文件。
{
"defaults": {
"key_property": "uuid",
"nodes_index": "default-index-node",
"relationships_index": "default-index-relationship",
"include_remaining_properties": true
},
"node_mappings": [
{
"condition": "hasLabel('Person')",
"index": "nodes-persons",
"type": "doc",
"properties": {
"name": "getProperty('firstName') + ' ' + getProperty('lastName')",
"created_at": "query('MATCH (n) WHERE id(n) = {id} RETURN toString(n.created_at) as value')"
}
},
{
"condition": "hasLabel('Company')",
"index": "nodes-companies",
"type": "doc",
"properties": {
"name": "getProperty('name')"
}
}
],
"relationship_mappings": [
{
"condition": "isType('WORKS_FOR')",
"index": "relationships_worksfor",
"type": "doc"
}
]
}
在这里,重要的是 “index” 部分,可以根据每个标签更改索引名称,并将索引与类型一一对应。
请自行更改 node_mappings 和 relationship_mappings 的内容。
相当自由,并且可以使用Cypher查询。
以上的内容应该也适用于Elasticsearch 6.x。
进行地图制作
你是否觉得无法使用ngram或者Kuromoji(形态素解析)? 确切地说,它们是可以使用的。
但是,由于无法在Neo4j中设置该映射,因此需要直接在Elasticsearch中进行映射设置。
由于映射无法后期更改,如果已经进行了索引,则需要先将其删除。
可以像普通的索引一样进行以下设置。
PUT nodes-persons
{
"settings":{
"analysis":{
"analyzer":{
"ja_ngram":{
"type":"custom",
"tokenizer":"ja_ngram_tokenizer"
}
},
"tokenizer":{
"ja_ngram_tokenizer":{
"type":"nGram",
"min_gram":"1",
"max_gram":"2",
"token_chars":[
"letter",
"digit"
]
}
}
}
},
"mappings": {
"doc": {
"properties": {
"name":{
"type": "text",
"analyzer":"ja_ngram"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
}
}
}
}
}
如果在执行PUT映射后重新启动Neo4j,它应该会按照此命令来创建索引。
对于日期时间,我有点困惑。Neo4j的DateTime属性默认设置了一个很难处理的映射。而且似乎无法直接将其转换为Elasticsearch的date类型。因此,我在mapping.json中首先将其转换为字符串,然后在映射中指定了格式并进行读取。
用Neo4j发起查询
以下是使用Cypher向Elasticsearch查询的示例方法:
调用ga.es.queryNode(‘{“query”:{“match_all”:{}}’)命令,并返回节点和得分:node和score。
然而,如果在mapping.js中更改了索引,似乎无法正常工作…
结束了
看起来非常有用。