使用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中更改了索引,似乎无法正常工作…

结束了

看起来非常有用。

广告
将在 10 秒后关闭
bannerAds