Статьи

Перенос данных Spring Neo4j с 3.x на 4.0 — графические объекты

В этой статье мы рассмотрим суть графов в Spring Data Neo4j: сущности графов, а именно узлы и отношения (как их называет Neo4j).

«Наконец, — вздыхают вы, преданные читатели, — что мне действительно интересно! Прямо там с« бесплатными напитками »и Netflix».

Честная оценка.

Хорошей новостью является то, что эти объекты в SDN 4.0 в основном такие же, как и в предыдущих версиях; Тем не менее, есть несколько отличий, которые мы выделим и с которыми будем ориентироваться — ничего, с чем эта толпа не может справиться!

Самое большое сходство в том, что вы все еще аннотируете свои POJO, которые представляют узлы и отношения.

Как и в предыдущих версиях SDN, отношения POJO необходимы только тогда, когда вам нужно сохранить свойства отношения, поэтому, если вам просто нужны простые отношения без свойств, достаточно просто пометить соответствующие свойства в вашем узле POJO!

Давайте подробнее рассмотрим каждый тип сущности.

Я Узлы, что вы думаете

Магазин фон Неймана ничто без своих покупателей! Итак, давайте посмотрим на некоторые важные части клиента  POJO, не так ли?

@NodeEntity
public class Customer {
    @GraphId
    private Long id;

    private String username;

    private String firstName;
    private String lastName;
    private String email;

    @Relationship(type = "FRIEND", direction = Relationship.UNDIRECTED)
    Set<Customer> friends;

    @Relationship(type = "PURCHASED", direction = Relationship.OUTGOING)
    Iterable<Purchase> purchases;

    @Relationship(type = "HAS_ADDRESS", direction = Relationship.OUTGOING)
    Address address;

    ...
}

A lot of this should look very familiar.

  • @NodeEntity is just the same as before.  When Customer is persisted to the graph, a :Customer label is automatically created and used.  Previously, if we wanted to use a different label, we would have had to have used the @TypeAlias annotation—not so anymore!  @NodeEntity has available an attribute called «label» that allows you to set a different label, e.g. @NodeEntity(label = «LifeBloodOfBusiness»).

  • @GraphId is needed just as before, and it must be of type Long; however, if you have a property called «id» of type Long, the @GraphId annotation is not required as SDN will automatically use the field for its purposes.  It’s worth noting that the type must be the non-primitive Long.  And, as an important reminder, remember that 0 is a valid value for a Neo4j node ID.

  • Other primitive (both single and array-based) and string fields are automatically persisted into the node.

  • What might jump out at you is the use of @Relationship.  Let’s talk about this a bit more.

Relationships Are Now a Lot Less Work

Spring Data Neo4j won’t judge you!

@Relationship has replaced both @RelatedTo and @RelatedToVia.  Recall that the former was used to relate a node to another node (or group of nodes) and that the latter was used to designate a relationship entity (recall what relationship entities are used for as stated above) to use for a specific relationship.

These two annotations have both been replaced by @Relationship.  Simpler is better!  SDN is smart enough to know what you mean based on the type of the field.  All that is required is a «type» and a «direction».

Also notice that Relationship.* (where «*» can be one of INCOMING, OUTOING, or UNDIRECTED) has replaced Direction.* when specifying the relationship’s direction.  It is important to note that while the use of UNDIRECTED simply ignores the relationship direction actually stored in the graph, the persisted relationship does not, in fact, lack direction.

«But what if you have relationships that are of the same name but point to different node types?» the astute reader (that is, you) is asking.  In previous versions of SDN, we had to specify an «enforceTargetType» attribute into the annotation.  Not so anymore!  SDN is smart enough to know what you mean, and so this kind of situation is made easier to deal with.

(It is worth noting that the target types must be of differeing types.)

Another quick reminder: If you are relating a group of nodes to your node POJO and need the group to be modifiable, you would generally use a Set<T> (or some other Collection-based container); otherwise, you should use Iterable<T> for read-only fields.  Also, be careful if order is important: A Set cannot relied about for order, while Iterable can.

Phew, okay, let’s now have a look at relationship entities!

A Graph Without Relationships Is Like a Day Without Sunshine!

Relationships form the heart of any graph—they are what give the graph meaning.

Название изображения

SHOW ME THE MONEY! …no, wait…

(Courtesy: indatimes.in and TriStar Pictures)

Now, ordinarily, we don’t need relationship POJOs if we are persisting relationships that have no properties; however, when we do need to persist properties on a relationship, we require the use of a relationship entity.

Let’s have a look at one!

@RelationshipEntity(type = "PURCHASED")
public class Purchase {
    @GraphId
    private Long id;

    @StartNode
    private Customer customer;

    @EndNode
    private Stock item;

    private int quantity = 0;

    ...
}

Again, a lot of similarities exist here with the previous version of SDN:

  • @RelationshipEntity operates just like it used to, with the «type» attribute being required (after all, what good is a relationship without a type/name?)
  • @GraphId is used in exactly the same way as for node entities, with exactly the same caveats and semantics.

  • @StartNode and @EndNode work just as before and are required, specifying the «source» of the relationship and the «destination» of the relationship.

So, as you can see, there really is no appreciable difference between older versions of SDN and SDN 4.0 when it comes to relationships.  Awesome!

Conclusion

In this post we have seen the differences and uses of the annotations that are at the heart of Spring Data Neo4j.  Node entities and relationship entities are both crucial to persisting and retrieving our graphs, and make our lives significantly easier when dealing with such an integration.

The good news is that the use of these entities, while similar and familar, have been improved to help speed up productivity and avoid some pitfalls that used to exist.

In the next post, we will have a quick look at indices in Spring Data Neo4j and wrap up this series. I know, I know—I’m just as sad as you are, but, all good things must come to an end.  Or not. Hopefully not.  

See you in the next post!