neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

41
INTELLIGENCE, Ltd ©2012 INTELLIGENCE, Ltd. All Rights Reserved. INTELLIGENCE, Ltd ©2012 INTELLIGENCE, Ltd. All Rights Reserved. Neo4j の ののののののののののののののの 「」 のののののののののの 「」 2016.01.25 清清 清

Upload: keiichiro-seida

Post on 16-Jan-2017

1.546 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

INTELLIGENCE, Ltd

©2012 INTELLIGENCE, Ltd. All Rights Reserved.

INTELLIGENCE, Ltd

©2012 INTELLIGENCE, Ltd. All Rights Reserved.

Neo4j の「データ操作プログラミング」から「ビジュアライズ」まで

2016.01.25

 清田 馨一郎

Page 2: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

自己紹介

【名前】 清田 馨一郎 (@seikei1874)

【所属】 キャリア Div. マーケティング企画統括部 データアナリティクス部 マーケティングテクノロジーグループ

【経歴】   2002 年 受託メインの会社に入社   PG から叩き上げで PM まで経験  大手企業の基幹システムからソーシャルゲーム開発まで幅広く経験

   2014 年 4 月からインテリジェンスへ JOIN部門内の KPI 集計、見える化を進めるシステムの開発、運用を担当

石抱き

Page 3: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

これから話す内容は、個人の見解であり、所属する組織、団体の見解ではありません。

「 At your own risk 」でお願いします。

3 | May 1, 2023 |

Page 4: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Neo4j の利用

サイト流入、回遊状況の集計 一時的に Neo4j に格納し、集計を簡単にしている

サイト回遊状況の可視化 まだ、実験段階

なぜ、 Neo4j を利用したのか? 遷移数が「不定」なので、 RDB では難易度が高いと思った

4 | May 1, 2023 |

Page 5: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Rest API / 組み込み (Embedded) API

5 | May 1, 2023 |

Page 6: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

アーキテクチャ図

6 | May 1, 2023 |

組み込み API REST API

JAVA( もしく

は、 Scala 、 Groovy などJAVA API が利用できる言語 )

Neo4j サーバー

アプリケーション

プログラミング言語

REST APIクライアント

データファイル

Neo4j

Page 7: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

REST API と組み込み APIREST API

Neo4j サーバを起動すれば、即利用可能 REST API なので、クライアンの言語、 FW は問わない 他サーバから呼べる HTTP 通信、 REST 解析が行わるので、若干遅い 基本は、こちらを利用する

組み込み API ( EmbeddedAPI ) JAVA API ( JVM で動く言語から利用可) 同じサーバからのみ Neo4j をデータストアとして利用し、大量、高速に処理したい ServerAPI を作成したい

7 | May 1, 2023 |

Page 8: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

集計できるまで

データ量 1 日分  120 万件くらい(計測したい部分のみ) Mac Book Pro で開発

最初 Cypher で、 CSV インポート 丸一日でも終わらない 1 ページを 1 ノードとして作成したので、特定のノード間で、数万エッジと偏りが生じ

る 終端ノードを取得する検索で、偏っていたエッジを全探索していた

ReTry ( 2 回目) 1PV を 1 ノードに変更 13 時間くらい 終端ノードの検索が遅い

8 | May 1, 2023 |

Page 9: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

集計できるまで

ReTry ( 3 回目) 組み込み API を利用 5 時間くらい やはり、終端ノードを検索するクエリが遅い

ReTry ( 4 回目) 投入データの前処理で、ユーザ毎に時系列で並べ替える 終端ノードの検索はしないで、追加した終端ノードを保持するように変更 30 分くらい 更に並列処理化して、 4,5 分程度に収める 最大で 2 億ノードくらいある状態でも実行したが処理速度は、それほど変わらなかった

9 | May 1, 2023 |

Page 10: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Neo4j   REST APIOGM(Object Graph Mapper)

SDN4(Spring Data Neo4j)http://projects.spring.io/spring-data-neo4j/

Java のアプリケーション FW では、一般的な SpringFramework のコンポーネントOGMベース。 GraphAware の社員がフルコミットで開発している。この社員は OGM のコミッターなので、 Java での開発であれば、 SDN4 を選択すべき

GraphAware Neo4j に関することを主力とした英国のベンチャー Neo4j関連の OSS を多数公開している

http://graphaware.com/products/ GraphAware Framework

https://github.com/graphaware/neo4j-framework/

10 | May 1, 2023 |

Page 11: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Neo4j JDBC https://github.com/neo4j-contrib/neo4j-jdbc

JDBC ドライバ経由で、 REST API と通信できるアプリケーションでの利用は現実的で無く、DB のビジュアルツールのドライバとして使用すべき

DataNucleus 様々な DB の ORM ライブラリ群らしい

Py2Neo 、 neo4jPHP など、様々な言語の FW がある詳しくは、 Neo4j デベロッパーサイト

http://neo4j.com/developer/language-guides/

11 | May 1, 2023 |

Page 12: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

OGM のサンプルソース

12 | May 1, 2023 |

Page 13: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

OGM サンプル

src└ main ├── java │ └── jp │   └── co │    └── inte │      ├── Neo4JOGMSample.java │      ├── Neo4jSessionFactory.java │      ├── domain │      │ ├── nodes │      │ │ ├── Movie.java │      │ │ └── Person.java │      │ └── relationships │      │ ├── Acted.java │      │ └── Directed.java │      └── service │        ├── GenericService.java │        ├── PersonService.java │        ├── Service.java │        └── impl │          └── PersonServiceImpl.java └── resources

13 | May 1, 2023 |

Page 14: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Neo4jOGMSample.java

14 | May 1, 2023 |

/** * 1956 年生まれの俳優 /女優の名前と、出演した映画のタイトルを出演します。 */public class Neo4JOGMSample {

public static void main(String... args) { PersonService service = new PersonServiceImpl();

Iterable p = service.findByBorn(1956); p.forEach(person -> { System.out.print(person.getName());

// Person ノードから「 ACTED_IN 」でリレーションシップされている Movie ノードを取得 List acteds = person.getActed(); acteds.forEach( acted -> { System.out.print(" : " + acted.getMovie().getTitle()); });

System.out.println(); }); }}

Page 15: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Neo4jSessionFactory.java

15 | May 1, 2023 |

import org.neo4j.ogm.session.Session;import org.neo4j.ogm.session.SessionFactory;

public class Neo4jSessionFactory { // Entity クラスがあるパッケージ名を渡す private final static SessionFactory sessionFactory = new SessionFactory("jp.co.inte.domain.nodes", "jp.co.inte.domain.relationships");

private static Neo4jSessionFactory factory = new Neo4jSessionFactory();

public static Neo4jSessionFactory getInstance() { return factory; }

private Neo4jSessionFactory() { }

public Session getNeo4jSession() { return sessionFactory.openSession("http://localhost:7474", "neo4j", "neo"); }}

Page 16: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

GenericService.java

16 | May 1, 2023 |

public abstract class GenericService<T> implements Service<T> { private static final int DEPTH_LIST = 0; private static final int DEPTH_ENTITY = 2; private Session session = Neo4jSessionFactory.getInstance().getNeo4jSession();

@Override public Iterable<T> findAll() { return session.loadAll(getEntityType(), DEPTH_LIST); }

@Override public T find(Long id) { return session.load(getEntityType(), id, DEPTH_ENTITY); }

public abstract Class<T> getEntityType();}

Page 17: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

PersonServiceImpl.java

17 | May 1, 2023 |

public class PersonServiceImpl extends GenericService<Person> implements PersonService {

@Override public Iterable<Person> findByBorn(int born) {

/** * リレーションシップも返さないと NodeEntity クラスの Relationship に値が入らないので注意 */ String query = "MATCH (p:Person)-[a:ACTED_IN|DIRECTED]->() where p.born = {born} return p,a";

Session session = Neo4jSessionFactory.getInstance().getNeo4jSession(); Map<String, Integer> params = new HashMap<>(); params.put("born", born);

return session.query(getEntityType(), query, params); }

@Override public Class<Person> getEntityType() { return Person.class; }}

Page 18: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

ノードのドメイン

18 | May 1, 2023 |

/* * アノテーションで LABEL 、ノードのプロパティ、リレーションシップタイプなどを指定します。 */@NodeEntity(label = "Movie")public class Movie {

@GraphId private Long id;

@Property(name = "title") private String title;

@Property(name = "tagline") private String tagline;

@Property(name = "released") private Integer released;

@Relationship(type = "ACTED_IN", direction = "INCOMING") private Person person;

/** Getter 、 Setter は省略 **/}

Page 19: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

リレーションシップのドメイン

19 | May 1, 2023 |

/* * リレーションシップのエンティティでは、開始、終了ノードもアノテーションで指定できます。 */@RelationshipEntity(type = "ACTED_IN")public class Acted { @GraphId private Long id;

@Property(name = "roles") private List<String> roles;

@StartNode private Person person; @EndNode private Movie movie;

/** 略 */}

Page 20: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Embedded API サンプルソース

20 | May 1, 2023 |

Page 21: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Embedded API

21 | May 1, 2023 |

/** * Neo4J 起動 */GraphDatabaseService graphDatabaseService = new GraphDatabaseFactory()   .newEmbeddedDatabaseBuilder(Paths.get("").toFile()) .newGraphDatabase();

/** * 実行中に Neo4j Shell で接続可能 */GraphDatabaseService graphDatabaseService = new GraphDatabaseFactory() .newEmbeddedDatabaseBuilder(Paths.get("").toFile()) .setConfig(ShellSettings.remote_shell_enabled, "true") .setConfig(ShellSettings.remote_shell_port, "5555") .setConfig(ShellSettings.remote_shell_read_only, "true") .newGraphDatabase();

// 終了graphDatabaseService.shutdown();

Page 22: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

22 | May 1, 2023 |

/* * Ctrl-C などの停止が発生した場合の処理 * Neo4J への接続を停止する。 */private static void registerShutdownHook(final GraphDatabaseService graphDatabaseService) {

Runtime.getRuntime().addShutdownHook(new Thread() {

@Override public void run() { graphDatabaseService.shutdown(); } });}

// 起動した Neo4j のインスタンスを渡すregisterShutdownHook(graphDatabaseService);

Page 23: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

23 | May 1, 2023 |

try (Transaction transaction = graphDatabaseService.beginTx()) { // ノードの作成 Node startNode = graphDatabaseService.createNode(DynamicLabel.label("LABEL")); Node endNode = graphDatabaseService.createNode(DynamicLabel.label("LABEL"));

// リレーションシップの作成 Relationship rel = startNode.createRelationshipTo(endNode, DynamicRelationshipType.withName("TYPE"));

// successs設定しないとプロパティを更新できない transaction.success();

// プロパティの設定 startNode.setProperty("property", "value"); rel.setProperty("property", "value");

transaction.success();}

Page 24: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

24 | May 1, 2023 |

for (Path path : traversal.traverse(node)) { pages.add((String) path.endNode().getProperty("url"));}

// トラバーサルTraversalDescription traversal = graphDatabaseService.traversalDescription() .relationships(DynamicRelationshipType.withName("TYPE"), Direction.OUTGOING) .evaluator(path -> {

Node node = path.endNode();

// 特定のラベルを持っていなければ含まない if (!node.hasLabel(DynamicLabel.label("LABEL"))) { return Evaluation.EXCLUDE_AND_CONTINUE; }

// 目的のプロパティを持っていたら、以降は枝切り String url = (String) node.getProperty("url"); if (url.matches(".*HOGE.*")) { return Evaluation.INCLUDE_AND_PRUNE; }

return Evaluation.INCLUDE_AND_CONTINUE; });

Page 25: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

REST API Neo4 J サーバを起動すれば、即利用可能 REST API なので、クライアンの言語、 FW は問わない 他サーバから呼べる HTTP 通信、 REST 解析が行わるので、若干遅い 基本は、こちらを利用する

組み込み API ( EmbeddedAPI ) JAVA API ( JVM で動く言語から利用可) 同じサーバからのみ Neo4j をデータストアとして利用し、大量、高速に処理したい ServerAPI を作成したい

25 | May 1, 2023 |

Page 26: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

26 | May 1, 2023 |

Server Plugin/ Unmanaged Extension

Page 27: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

最初に まとめ

標準の REST API と Cypher の組み合わせで十分なことが多いがパフォーマンスや、トラーバサルを細かく定義したい場合がある

Embedded API を利用すればパフォーマンスの問題は解決できるがServerモードとの併用ができない

REST API 経由で Embedded API が利用できる Server API を自作する

Server API は、「 Server Plugin 」「 Unmanaged Extension 」

「 Unmanaged Extension 」は、 Neo4j の管轄外となる どのような影響があるが把握していないが、オフィシャルでは利用を推奨していない

「 Unmanaged Extension 」では、 JSON以外で返せる

27 | May 1, 2023 |

Page 28: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

アーキテクチャ図

28 | May 1, 2023 |

Neo4j サーバ

RESTクライア

ント

REST サーバ(JAX-RS)

Neo4j の REST API

UnmanagedExtension

Server Plugin

Embedded API データファイル

HTTP

HTTP

Page 29: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Server Plugin の作成

Java 。「 org.neo4j.server.plugins.ServerPlugin 」を継承する継承先から渡される「 GraphDatabaseService 」を利用して処理するServerPlugin から返せる値

Node型 Relationship型 Path型 Java プリミティブ型 String型 org.neo4j.server.rest.repr.Representation

ServiceLoader なので、 META-INF/services配下に「 org.neo4j.server.plugins.ServerPlugin 」ファイルを作成し、そのファイルに plugin にしたいクラスを記述する

$ cat src/main/resources/META-INF/services/org.neo4j.server.plugins.ServerPluginjp.co.inte.Sample

jar を作成して、 ${NEO4J_HOME}/plugin に配置する

29 | May 1, 2023 |

Page 30: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

30 | May 1, 2023 |

import org.neo4j.graphdb.GraphDatabaseService;import org.neo4j.graphdb.Result;import org.neo4j.graphdb.Transaction;import org.neo4j.server.plugins.Name;import org.neo4j.server.plugins.PluginTarget;import org.neo4j.server.plugins.ServerPlugin;import org.neo4j.server.plugins.Source;

public class Sample extends ServerPlugin {

@Name("plugin_sample") @PluginTarget(GraphDatabaseService.class) public Long count(@Source GraphDatabaseService graphDb) {

Long count = 0L;

try(Transaction tx = graphDb.beginTx()) { Result result = graphDb.execute("MATCH (n) return count(n) as cnt"); count = result.next(); count = (Long)ret.get("cnt"); } return count; }}

Page 31: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

31 | May 1, 2023 |

$ curl http://localhost:7474/db/data/ { "extensions" : {    "Sample" : {      "plugin_sample" : "http://localhost:7474/db/data/ext/Sample/graphdb/plugin_sample"   } }, "node" : "http://localhost:7474/db/data/node", "node_index" : "http://localhost:7474/db/data/index/node", "relationship_index" : "http://localhost:7474/db/data/index/relationship", "extensions_info" : "http://localhost:7474/db/data/ext", "relationship_types" : "http://localhost:7474/db/data/relationship/types", "batch" : "http://localhost:7474/db/data/batch", "cypher" : "http://localhost:7474/db/data/cypher", "indexes" : "http://localhost:7474/db/data/schema/index", "constraints" : "http://localhost:7474/db/data/schema/constraint", "transaction" : "http://localhost:7474/db/data/transaction", "node_labels" : "http://localhost:7474/db/data/labels", "neo4j_version" : "2.3.0" }

Page 32: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Unmanaged Extension の作成

32 | May 1, 2023 |

package jp.co.inte;

import org.neo4j.graphdb.GraphDatabaseService;import javax.ws.rs.*;import javax.ws.rs.core.Context;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.Response;import java.nio.charset.Charset;

@Path("/helloworld")public class UnmanagedPluginSample {

private final GraphDatabaseService graphDatabaseService;

public UnmanagedPluginSample(@Context GraphDatabaseService graphDatabaseService) { this.graphDatabaseService = graphDatabaseService; }

@GET @Produces(MediaType.TEXT_PLAIN) @Path("/{nodeId}") public Response hello(@PathParam("nodeId") long nodeId) { return Response.status(Response.Status.OK).entity( ("Hello World, nodeId=" + nodeId).getBytes( Charset.forName("UTF-8") ) ).build(); }}

Page 33: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

Unmanaged Extension の作成

「 neo4j-server.properties 」に呼び出したい Extension を記述する

org.neo4j.server.thirdparty_jaxrs_classes=jp.co.inte=/sample/unmanage

この例では、パッケージ「 jp.co.inte 」にあるクラス群を「 /sample/unmanage 」で呼ぶ定義。

サンプルコードのパスは「 /sample/unmanage/helloworld 」となる。

33 | May 1, 2023 |

Page 34: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

もう一度 まとめ

標準の REST API と Cypher の組み合わせで十分なことが多いがパフォーマンスや、トラーバサルを細かく定義したい場合がある

Embedded API を利用すればパフォーマンスの問題は解決できるがServerモードとの併用ができない

REST API 経由で Embedded API が利用できる Server API を自作する

Server API は、「 Server Plugin 」「 Unmanaged Extension 」

「 Unmanaged Extension 」は、 Neo4j の管轄外となる どのような影響があるが把握していないが、オフィシャルでは利用を推奨していない

「 Unmanaged Extension 」では、 JSON以外で返せる

34 | May 1, 2023 |

Page 35: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

ビジュアライゼーション

35 | May 1, 2023 |

Page 36: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

ビジュアライゼーション

linkurious.jshttps://github.com/Linkurious/linkurious.js

フランスのベンチャー linkurious(https://linkurio.us/) が提供しているSigma.jsベースの JS ライブラリ。

REST API 経由で、 Cypher を実行してビジュアライズする JavaScript が標準で用意

36 | May 1, 2023 |

Page 37: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

ビジュアライゼーション

Gephihttps://gephi.wordpress.com/ ネットワーク分析 GUIツール

Neo4j Shell-tools を利用すれば、 Gephi で読み込めるデータ形式で出力可能https://github.com/jexp/neo4j-shell-tools

37 | May 1, 2023 |

Page 38: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

ビジュアライゼーション

Popoto.jshttp://www.popotojs.com/

d3.jsベースの JavaScript ライブラリ インタラクティブなデータ探索が可能

38 | May 1, 2023 |

Page 39: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

まとめ

まずは、 REST API+ REST フレームワークで検討しよう。パフォーマンスがでなければ、 Server Plugin を検討しよう。Embeddedモードは最後の手段

Neo4j をバッチ処理のみに使用するなら、 Embeddedモード

ブラウザでビジュアライズしたければ、 Linkrious.js が良いネットワーク分析がしたければ、 Gephi

39 | May 1, 2023 |

Page 40: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

お願い

知見、試してみた事の共有を是非!! GraphAware 、 DataNucleus の使い方

ネットワーク分析 Gephi の使い方

Spark GraphX と Neo4j の関係性– GraphX のデータストアに Neo4j が利用できる?

複雑ネットワーク分析を Neo4j で。– ネットワークの特徴量、類似性、伝播モデルなどなど

40 | May 1, 2023 |

Page 41: Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで

41 | May 1, 2023 |