楼主: jieforest

Neo4j用Spring Data Neo4j建模

[复制链接]
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
11#
 楼主| 发表于 2013-8-5 15:16 | 只看该作者
#A Cass backed by a Neo4j node
#1 Maps to name property on underlying node
#2 Ensures userId field is indexed
#3 Optional annotation, maps to userId property on underlying node
#4 Property containing Neo4j node ID

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
12#
 楼主| 发表于 2013-8-5 15:17 | 只看该作者
Properties

Within a class annotated with @NodeEntity, by default SDN will treat all simple fields as being representative of Neo4j properties on the backing node. In this context, simple is any primitive or its associated wrapper class, strings, or objects capable of being converted to a string through a Spring conversion service.

Collections of any of these previously mentioned types are also included, where these collections are ultimately stored as an array on the Neo4j node. In the preceding domain example, this means that the name (#1) and title fields defined on the User and Movie classes, respectively, will get mapped as Neo4j properties with those same names without you needing to lift a finger! Having said that, you can optionally annotate fields with @GraphProperty if you'd like to be more explicit (as you've done with the userId field at #3); however, it is not strictly necessary.

What about custom property types?

The core Spring framework comes with a general type conversion system that allows you to write and register custom type conversion logic that can transform a specific (nonprimitive) class to a string representation and back again. SDN has already registered some conversion services for you that handle enums and dates.

So if, for example, you defined a java.util.Date field on a node entity when the entity is due to get persisted, Spring recognizes that there is a custom converter defined for date fields and uses it to convert the Date property to a string that is then stored in the graph; the reverse occurs when reading the data out of the graph and back into the node entity field.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
13#
 楼主| 发表于 2013-8-5 15:17 | 只看该作者
This means that you can take advantage of this same mechanism to handle any custom class types that you may want to use, say, perhaps, a phone number object. You'll need to write a custom converter and then register this converter with Spring. For more details on how to do this, refer to

http://static.springsource.org/s ... n.html#core-convert

Note if you do not register a converter, SDN will still save a string version of your object into the database, however, it will simply be based on whatever is returned from the toString() method.
Now you'll probably have noticed that an additional field appears to have snuck in to both the User and Movie node entities, namely nodeId, annotated with @GraphId. This is a mandatory SDN requirement when using simple object mapping.

Without going into too much detail just yet, simple object mapping is one of the strategies employed by SDN to perform the physical mapping between your domain entity and backed graph entity. Using this strategy, SDN needs to have a field where it can store the underlying ID of the node backing the entity. The @GraphId annotation (#4) serves to mark the field that you've set aside for SDN to store this value in.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
14#
 楼主| 发表于 2013-8-5 15:18 | 只看该作者
Indexed properties

As it is generally considered bad practice for the application to rely on the Neo4j node ID as the external unique identifier of an object, it is important to be able to have some other way of looking up a node. The addition of the @Indexed annotation (#2) on the userId field ensures that lookups and queries can be performed against this user based on this field.

Under what index names are these annotated properties stored?

By default, SDN will create an exact lookup index per entity under the simple (not fully qualified) name of the class (User in this case). If you wanted to look up a user (say, John with user ID john001) using native code, it would be coded as follows:
  1. 1.IndexManager indexManager = aGraphDatabaseService.index();      
  2. 2.Index<Node> userIdIndex = indexManager.forNodes("User");
  3. 3.IndexHits<Node>indexHits = userIdIndex.get("userId","john001");
  4. 4.Node johnNode = indexHits.getSingle();
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
15#
 楼主| 发表于 2013-8-5 15:18 | 只看该作者
So be careful in how you name and structure your domain entities. It is generally not advisable to have two domain entities with the same name, even if they're in separate packages due to this default indexing behavior. A bad example of this may be to have one User domain entity under a "core" package and another under "admin."

Though it is possible to override this default behavior by setting the indexName attribute within the @Indexed annotation, it can be confusing to those who may not be aware of this behavior and could result in unforeseen results if you're not careful.

Relationships to other entities

Finally, there are also the relationships between node entities. You'll be pleased to learn that these are also simply mapped as reference fields on the entity. However, before we get into the details for how this is done, you need to learn about relationship entities.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
16#
 楼主| 发表于 2013-8-6 10:35 | 只看该作者
Modeling relationship entities

A relationship entity is simply the relationship version of a node entity. It refers to a Java class that is ultimately represented and backed by a Neo4j relationship in the underlying graph database. Neo4j treats relationships as first-class citizens, which, just like nodes, can have their own identifier and set of properties if required. Thus, SDN also allows them to be represented as entities in their own right.



Figure 3 Social network model with relationships highlighted that could potentially be modeled as relationship entities

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
17#
 楼主| 发表于 2013-8-6 10:36 | 只看该作者
In this section, we'll cover what is required to model the physical Neo4j relationship entity as a POJO itself, while in the next section, we'll show what is required from the node entity's perspective to refer to other node entities through these modeled relationships, as well as through more simple mechanisms.

NOTE There will probably be many relationships defined within your physical Neo4j model, but this does not automatically mean that all of them need to be modeled as relationship entities in SDN!

SDN relationship entities are generally only required for relationships that have their own set of properties, and that, together with these properties, provide context to the relationship. We'll refer to these relationships as rich relationships because of the additional data they contain over and above the relationship type.

The HAS_SEEN relationship is a perfect example of this, with its additional stars property providing more context to the relationship, which indicates not just that a user has seen a movie, but also how he or she may have rated it. In the social network model, this relationship with all its associated information has been defined as the Viewing class, as shown in listing 3.

Contrast this to the IS_FRIEND_OF relationship, which alone is all that is required to understand the relationship between two users—that is, that they're friends. These simple type relationships (that is, the IS_FRIEND_OF relationships) can still be referenced, and you'll see how this is done in the next section, but there is no additional benefit in defining a whole new class to represent it.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
18#
 楼主| 发表于 2013-8-6 10:36 | 只看该作者
Listing 3 Viewing class: relationship entity
  1. 01.@RelationshipEntity(type = "HAS_SEEN")                 #A
  2. 02.public class Viewing {
  3. 03.@GraphId                            #1
  4. 04.Long relationshipId;                    #1
  5. 05.
  6. 06.@StartNode                      #2
  7. 07.User user;                      #2
  8. 08.
  9. 09.@EndNode                            #3
  10. 10.Movie movie;                        #3
  11. 11.
  12. 12.Integer stars;                      #B
  13. 13.}
复制代码

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
19#
 楼主| 发表于 2013-8-6 10:36 | 只看该作者
#A Class is backed by a Neo4j relationship
#1 Property containing Neo4j relationship ID
#2 User node from which relationship originates (outgoing)
#3 Movie node at which relationship ends (incoming)
#B Maps to stars property on underlying relationship

The @RelationshipEntity annotation is applied to classes to indicate that it represents a Neo4j relationship. The annotation takes a type property used to indicate the name of the Neo4j relationship type used internally. If not specified, the name of the class will be considered to be the physical name used within Neo4j as well. As with the node entity, the relationship entity has the same requirement for a @GraphId annotated field (#1), this time for storing the underlying relationship ID.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
20#
 楼主| 发表于 2013-8-6 10:37 | 只看该作者
If you'd like to access the node entities on either side of this relationship you'll need to provide a field for each of these and annotate them with @StartNode (#2) and @EndNode (#3). For the Viewing class example, the User node entity starts (has the outgoing) relationship to the ending Movie entity.

In terms of what is required to model a Neo4j relationship, that is it. There is, however, generally not much point in defining relationship entity classes in isolation. They're almost always referred to through one or more fields on associated node entities. In the next section, we go in to detail with the whole area of how node entities can refer to other node entities, through simple references, but also through POJO-modeled relationships.

To provide full context for this example, however, listing 4 provides a sneak preview of how the User node entity, as well as the Movie node entity, refer to the Viewing relationship entity class through their views field.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表