1

バッチ挿入 API を使用して大量のデータを Neo4J データベースにインポートしています。データベースは、読み取り専用 API (組み込みサーバー) を強化するために使用されます。

インポートするデータは、既存のデータベース スキーマに保持されているドメインの概念/エンティティの非常に近いコピーです。これらの関係を利用して、データ内の追加の関係を見つけ、Web サイトの追加機能を推進しています。

たとえば、 person-[:reads]->book-[:writtenBy]->person があった場合、これは追加の関係 person-[:isAFanOf]->person を意味すると判断する可能性があります。これにより、コードがもう少し明確になり ("is fan of" 関係について話しているように)、クエリとトラバーサルの多くは 2 つのエンティティ間を行き来する必要がないため、パフォーマンスが大幅に向上します。

これを行うのに最適な場所はどこですか?私たちはいくつかの提案を思いつきました:

  • バッチ挿入コードでは、関連するすべてのエンティティがインポートされた後。
  • ネットワークを「スパイダー」するプロセスでは、推測された関係を追加するユーザーを探し、これらを追加してから、同じように近隣をスケジュールします。
  • API での読み取り時 - データを消費するユーザーの初期ロード時間がかなり長くなる可能性があるため、考えられません

もう 1 つの問題は、データベースが 24 時間ごとに新しく作成されたデータで更新されるため、完全なインポートと部分的なインポートのケースで役立つものが必要なことです。

例/経験は大歓迎です。

4

3 に答える 3

3

Cypher を使用する必要がありますか? そうでない場合、6,000 万のノードがあるため、リストされている暗号クエリtstormsは見栄えがよく、正常に動作しますが、それらすべてのトランザクションを実行するため、メモリの使用量が大きくなる可能性があるため、難しい場合があります。

これを手動で行うには、Java API (Java を使用していると仮定します) を使用できます。

        RelationshipType readsRelationshipType = DynamicRelationshipType.withName("reads");
        RelationshipType writtenByRelationshipType = DynamicRelationshipType.withName("writtenBy");
        RelationshipType isAFanOfRelationshipType = DynamicRelationshipType.withName("isAFanOf");
        int counter = 0;
        Transaction tx = db.beginTx();
        try {
            for (Node reader : GlobalGraphOperations.at(db).getAllNodes()) {
                for (Relationship reads : reader.getRelationships(Direction.OUTGOING, readsRelationshipType)) {
                    Node book = reads.getOtherNode(reader);
                    for (Relationship writtenBy : book.getRelationships(Direction.OUTGOING, writtenByRelationshipType)) {
                        Node author = reads.getOtherNode(book);
                        try {
                            reader.createRelationshipTo(author, isAFanOfRelationshipType);
                        } catch (Exception e) {
                            // TODO: Something for exception
                        }
                    }
                }
                counter++;
                if (counter % 100000 == 0) {
                    tx.success();
                    tx.finish();
                    tx = db.beginTx();
                }
            }
            tx.success();
        } catch (Exception e) {
            tx.failure();
        } finally {
            tx.finish();
        }
    }

このコードは、エラー処理とトランザクション数を想定していますが、必要に応じて調整できます。

于 2013-04-29T15:19:58.187 に答える
2

おそらくインポートの直後にそれを行うでしょう。次の Cypher ステートメントでうまくいくはずです。

START p=node(*)
MATCH p-[:reads]->book-[:writtenBy]->p2
CREATE p-[:isAFanOf]->p2
于 2013-04-29T13:03:20.527 に答える