新しいプロジェクトに取り組み始めています...ソーシャルネットワークプラットフォームにサービスを提供するRESTfulレイヤー。
Neo4jはメインデータストアの私の明白な選択でした。以前はNeoを使用する機会がありましたが、 SpringDataの機能を利用してPOJOをノードにマッピングすることは非常に便利でした。
目標:
レイヤーは、URLから参照できるエンティティ/オブジェクト関連のプロパティと接続を定義するFacebookGraphAPIに似たサポートを提供する必要があります。FBグラフAPI
可能であれば、ドメインエンティティとの間でシリアル化される転送オブジェクトを避け、クライアントとの間で転送されるJSONとしてドメインpojoを使用したいと思います。
例:
HTTP GET / profile / {id} /?fields = ...&connections = ...応答は、要求されたURLを含むプロファイルオブジェクトになります。
HTTP GET / profile / {id} / stories /?fields = ..&connections = ...&page = ..&sort = ...応答は、要求されたストーリーオブジェクトのリストになります。
関連するバージョン:
- Spring Framework 3.1.2
- Spring Data Neo4j 2.1.0.RC3
- Spring Data Mongodb 1.1.0.RC1
- AspectJ 1.6.12
- ジャクソン1.8.5
簡単にするために、プロファイル、ストーリーノード、およびそれらの間のロール関係があります。
public abstract class GraphEntity {
@GraphId
protected Long id;
}
プロファイルノード
@NodeEntity
@Configurable
public class Profile extends GraphEntity {
// Profile fields
private String firstName;
private String lastName;
// Profile connections
@RelatedTo(type = "FOLLOW", direction = Direction.OUTGOING)
private Set<Profile> followThem;
@RelatedTo(type = "BOOKMARK", direction = Direction.OUTGOING)
private Set<Story> bookmarks;
@Query("START profile=node({self}) match profile-[r:ROLE]->story where r.role = FOUNDER and story.status = PUBLIC")
private Iterable<Story> published;
}
ストーリーノード
@NodeEntity
@Configurable
public class Story extends GraphEntity {
// Story fields
private String title;
private StoryStatusEnum status = StoryStatusEnum.PRIVATE;
// Story connections
@RelatedToVia(type = "ROLE", elementClass = Role.class, direction = Direction.INCOMING)
private Set<Role> roles;
}
役割の関係
@RelationshipEntity(type = "ROLE")
public class Role extends GraphEntity {
@StartNode
private Profile profile;
@EndNode
private Story story;
private StoryRoleEnum role;
}
最初はAspectJサポートを使用しませんでしたが、POJOと実際のノードの間に仕切りを生成するため、ユースケースに非常に役立ちます。したがって、リクエストとドメイン駆動型に応じてプロパティ/接続を簡単にリクエストできます。デザインアプローチはとてもいいようです。
質問1-AspectJ:
オブジェクトのデフォルトフィールドを定義したいとします。これらのフィールドは、URLで要求されたかどうかに関係なくクライアントに返されます...したがって、これらのフィールドで@FETCHアノテーションを試しましたが、使用すると機能しないようです。 AspectJ。現時点ではそのようにしています。
public Profile(Node n) {
setPersistentState(n);
this.id = getId();
this.firstName = getFirstName();
this.lastName = getLastName();
}
それを達成するための正しいアプローチですか?AspectJを使用している場合でも、@ FETCHアノテーションをサポートする必要がありますか?AspectJ + Neo4jについて話している例/ブログで、ほとんど何も見つかりませんでした。
質問2-ページネーション:
たとえば、特定の接続を要求するときにページネーションをサポートしたい
/ profile / {id} / stories /、ストーリーが以下のように関連している場合
// inside profile node
@RelatedTo(type = "BOOKMARK", direction = Direction.OUTGOING)
private Set<Story> bookmarks;
/ profile / {id} / stories /、以下のように関連するストーリーの場合
// inside profile node
@Query("START profile=node({self}) match profile-[r:ROLE]->story where r.role = FOUNDER and story.status = PUBLIC")
private Iterable<Story> published;
ページ付けは、@Query ||のいずれかですぐにサポートされますか @RelatedTo || @RelatedToViaは、Set / List / Iterableの代わりにPageableインターフェイスを使用してPageを取得しますか?制限と並べ替えは、クライアントからの要求に応じて動的である必要があります... Cypher Query DSLを使用してそれを達成できますが、基本を使用することを好みます。他のアプローチは喜んで受け入れられます。
質問3-{self}を使用した@Query:
ちょっとばかげた質問ですが、仕方がありません:)、ノードエンティティ内で@Queryを使用する場合({self}パラメータ}を使用する場合、戻り型はIterableである必要があります。これは意味があります。例を見てみましょう。 。
// inside profile node
@Query("START profile=node({self}) match profile-[r:ROLE]->story where r.role = FOUNDER and story.status = PUBLIC")
private Iterable<Story> published;
公開された接続が要求された場合:
// retrieving the context profile
Profile profile = profileRepo.findOne(id);
// getting the publishe stories using AspectJ - will redirect to the backed node
Iterable<Story> published = profile.getPublished();
// set the result into the domain object - will throw exception of read only because the type is Iterable
profile.setPublished(published);
そのための回避策はありますか?これは、Profile内で@Transiantになる別のプロパティを作成していません。
質問4-漸化式:
推移的/再帰的関係に問題があります。ストーリーで新しいプロファイルロールを割り当てると、リレーションエンティティロールに@EndNodeストーリーが含まれ、ロール接続が含まれます...そのうちの1つは上記のコンテキストロールであり、終了することはありません:) ...これらの終わりのない関係を作成しないようにSpringデータエンジンを構成する方法はありますか?
質問5-トランザクション:
前に言及したはずですが、Neo4j DBにRESTサーバーを使用しています。以前の記事から、トランザクションですぐに使用できるサポートがないことを理解していますか?組み込みサーバーを使用するときのように、私は次のコードを持っています...
Profile newProfile = new Profile();
newProfile.getFollowThem().add(otherProfile);
newProfile.getBookmarks().add(otherStory);
newProfile.persist(); // or profileRepo.save(newProfile)
これはRESTサーバーを使用するときにトランザクションで実行されますか?ここにはいくつかの操作がありますが、1つが失敗した場合、すべてが失敗しますか?
質問6-Mongo+Neo4j:
フィード、コメント、マッサージなど、リレーショナルな性質を持たないデータを保存する必要があります。これらを保存するためにMongoDB
との統合を考えました。クロスストアサポートを使用して、ドメインpojoフィールド/接続をmongo / neo4jの両方に分割できますか?AspectJをサポートしますか?
今のところは以上です....上記で提示したアプローチに関するコメントは大歓迎です..ありがとうございます。