1

Spring-Data を SpringBoot と共に使用して、Neo4j グラフ データベースにデータを入力しています。

次の Neo4j エンティティを定義しました。

Source実体 -->

@NodeEntity
public class Source implements Comparable<Source> {

    @GraphId private Long id;

    private String name;
    private SourceType type;
    private String dataStoreName;
    private String dataStoreDesc;

    private Source() {
        // Empty constructor required as of Neo4j API 2.0.5
    };

    public Source(String name, SourceType type, String dataStoreName, String dataStoreDesc) {
        this.name = name;
        this.type = type;
        this.dataStoreName = dataStoreName;
        this.dataStoreDesc = dataStoreDesc;
    }
    @Relationship(type = "CONTAINS", direction = Relationship.UNDIRECTED)
    public Set<Field> fields;

    public void contains(Field field) {
        if (fields == null) {
            fields = new HashSet<Field>();
        }
        fields.add(field);
    }


    /* Getter and Setters */

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public SourceType getType() {
        return type;
    }

    public void setType(SourceType type) {
        this.type = type;
    }

    public String getDataStoreName() {
        return dataStoreName;
    }

    public void setDataStoreName(String dataStoreName) {
        this.dataStoreName = dataStoreName;
    }

    public String getDataStoreDesc() {
        return dataStoreDesc;
    }

    public void setDataStoreDesc(String dataStoreDesc) {
        this.dataStoreDesc = dataStoreDesc;
    }

    public Set<Field> getFields() {
        return fields;
    }

    public void setFields(Set<Field> fields) {
        this.fields = fields;
    }

    @Override
    public int compareTo(Source other) {
        String name = other.getName();
        SourceType type = other.getType();
        if(this.name.equalsIgnoreCase(name) && this.type.equals(type))
            return 0;

        return -1;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((type == null) ? 0 : type.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Source other = (Source) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (type != other.type)
            return false;
        return true;
    }

}

Fieldエンティティ-->

@NodeEntity
    public class Field implements Comparable<Field> {

        @GraphId private Long id;

        private String name;
        private FieldType fieldType;
        private SourceType sourceType;

        private String logicalName;
        private String dataType;
        private String dataSize;
        private String description;

        private Field() {
            // Empty constructor required as of Neo4j API 2.0.5
        };

        public Field(String name, FieldType fieldType, SourceType sourceType, String logicalName, String dataType, String dataSize, String description) {
            this.name = name;
            this.fieldType = fieldType;
            this.sourceType = sourceType;
            this.logicalName = logicalName;
            this.dataType = dataType;
            this.dataSize = dataSize;
            this.description = description;
        }
        @Relationship(type = "MAPS-TO", direction = Relationship.UNDIRECTED)
        public Set<Field> fields;

        public void mapsTo(Field field) {
            if (fields == null) {
                fields = new HashSet<Field>();
            }
            fields.add(field);
        }

        /* Getter and Setters */

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public FieldType getFieldType() {
            return fieldType;
        }

        public void setFieldType(FieldType fieldType) {
            this.fieldType = fieldType;
        }

        public SourceType getSourceType() {
            return sourceType;
        }

        public void setSourceType(SourceType sourceType) {
            this.sourceType = sourceType;
        }

        public String getLogicalName() {
            return logicalName;
        }

        public void setLogicalName(String logicalName) {
            this.logicalName = logicalName;
        }

        public String getDataType() {
            return dataType;
        }

        public void setDataType(String dataType) {
            this.dataType = dataType;
        }

        public String getDataSize() {
            return dataSize;
        }

        public void setDataSize(String dataSize) {
            this.dataSize = dataSize;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public Set<Field> getFields() {
            return fields;
        }

        public void setFields(Set<Field> fields) {
            this.fields = fields;
        }

        @Override
        public int compareTo(Field other) {
            String name = other.getName();
            FieldType fieldType = other.getFieldType();
            SourceType sourceType = other.getSourceType();
            if(this.name.equalsIgnoreCase(name) && this.fieldType.equals(fieldType) && this.sourceType.equals(sourceType))
                return 0;

            return -1;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((fieldType == null) ? 0 : fieldType.hashCode());
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            result = prime * result + ((sourceType == null) ? 0 : sourceType.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Field other = (Field) obj;
            if (fieldType != other.fieldType)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            if (sourceType != other.sourceType)
                return false;
            return true;
        }


    }

したがって、Source CONTAINS複数Fieldの s。aFieldMAPS-TO1 つ以上の他Fieldの s です。

それぞれSourceSourceType.

私の異なるSourceTypeのは、プロデューサー、インバウンド、ステージング、中間、アウトバウンド、コンシューマーです。

public enum SourceType {
        PRODUCER, INBOUND, STAGING, INTERMEDIATE, OUTBOUND, CONSUMER;
    }

それぞれFieldFieldType.

私の異なるFieldTypeものは次のとおりです。FILE_FIELD、DB_COLUMN。

public enum FieldType {
    FILE_FIELD, DB_COLUMN;
}

私のデータ系統は次のとおりです: PRODUCER --> INBOUND --> STAGING --> INTERMEDIATE --> OUTBOUND --> CONSUMER

私は現在Field、 CONSUMERに a を指定すると、 PRODUCER までSourceその系統を追跡できる高度Sourceな Cypher クエリを探しています。

Field同様に、 PRODUCERSourceに a を指定すると、その系統をCONSUMER まで追跡できるクエリも探していますSource

shortestPath関数と関数を使用してクエリを作成しようとしましたneighborsが、探している結果が得られないようです。

任意の提案/ポインタをいただければ幸いです。

前もって感謝します !

更新-1

私のデータ系統の背景: 私のアプリケーションは外部アプリケーション (PRODUCE) からファイルを取得します。ファイル内のフィールドに入力された外部アプリケーションのデータベース テーブル/列を認識しています。ここでは、PRODUCER が私のSourceノードになります。外部アプリケーション (ファイルに入力された) の各 table.column はFieldノードであり、PRODUCERSourceノードはCONTAINSすべてのノードと関係を持ちFieldます (ファイルに入力された外部アプリケーション データベース テーブルの table.column を表します)。

外部アプリケーションからのファイルは INBOUND と呼ばれます。コンマ区切りファイルです。ファイルに含まれるフィールド名とその順序を認識しています。ここでは、INBOUND がSourceノードになります。ファイル内の各フィールドはFieldノードになり、INBOUNDSourceノードはCONTAINSすべてのノードと関係を持ちFieldます (受信ファイルのファイル フィールドを表します)。またField、INBOUNDの各ノードは、PRODUCERのノードと関係がありSourceます(1 対 1 のマッピング)。MAPS_TOFieldSource

同様のワークフローで、次の段階は STAGING と呼ばれ、受信ファイル フィールドをデータベース テーブル/列にロードします。ここでは、STAGING がSourceノードになり、(ファイル フィールドをロードする) データベース テーブルの各列がFieldノードを表します。FieldSTAGING ソース ノードは、すべてのノード (ファイル フィールドをロードする db テーブルの db table.column を表す)と CONTAINS 関係を持ちます。またField、STAGINGの各ノードは、INBOUNDのノードと関係がありSourceます(1 対 1 のマッピング)。MAPS_TOFieldSource

同様に、私の次のステージは中級です。この段階では、入力ファイルのフィールドをロードしたテーブルに対してクエリを実行し、出力を別のファイルにフラッシュします (ビジネス ユース ケースに基づいて、テーブル列のすべてまたはサブセットのみをクエリすることを選択できます)。入力ファイルから取り込まれます)。どのフィールドがどの順序で INTERMEDIATE ファイルに入るかを知っています。ここで、INTERMEDIATE は私のSourceノードであり、INTERMEDIATE ファイルに入る各フィールドは私のノードを表しFieldます。また、INTERMEDIATESourceは、中間ファイル内のフィールドを表すCONTAINSすべてのノードと関係があります。Fieldまた、これらの各FieldノードはMAPS_TO、STAGING ソースのフィールドと関係があります (1 対 1 のマッピング)。

同様に、OUTBOUND ステージ、最後に CONSUMER ステージがあります。

…(血統を視覚化できるようになったと思います)

私のクエリの目的は、たとえば、Field名前 (PRODUCER の table.column を表す) を入力として指定した場合、その系統を CONSUMER (つまり、私の系統の最後の段階) まで追跡できるようにすることです。

4

2 に答える 2

0

Field同様に、 PRODUCERSourceに a を指定すると、その系統をCONSUMER まで追跡できるクエリも探していますSource

データモデルと要件をまだ完全に理解しているとは思いませんが、このクエリのアイデアは次のとおりです。

MATCH
  (:Field  {name: { fieldName } })<-[:CONTAINS]-
  (:Source {type: "PRODUCER"    })-[:MAPS_TO]->
  (:Source {type: "INBOUND"     })-[:MAPS_TO]->
  (:Source {type: "STAGING"     })-[:MAPS_TO]->
  (:Source {type: "INTERMEDIATE"})-[:MAPS_TO]->
  (:Source {type: "OUTBOUND"    })-[:MAPS_TO]->
  (consumer:Source {type: "CONSUMER"    })
RETURN consumer
于 2016-11-21T18:17:29.817 に答える