Neo4j SDN4 和内部 ID 的正确使用
Neo4j SDN4 and a correct usage of internal Ids
我读到将 Neo4j 内部 ID 用于外部目的不是一个好的做法。
我认为我的 SDN4/Neo4j 应用程序出错了,因为我到处都在使用内部 ID。
我的应用程序中的每个 SDN 4 节点实体都有以下 属性:
@GraphId
private Long id;
我将这个长值用作我的 Web 应用程序 URL 的一部分。例如
/products/3245234
其中 3245234
是此产品节点实体的内部 Neo4j 标识符。
从 Neo4j 的角度来看是否安全 - 以这种方式使用内部 ID?如果不是,能否提供一个新代理键如何解决此问题的示例。
从应用程序的角度来看,使用 Neo4j 内部 ID 是安全的,因为使用它们不会破坏应用程序中的任何内容。
也就是说,Neo4j 的内部 ID 被回收了,我的意思是,如果一个节点或关系的内部 ID 为 12345,并且在某个时候该节点或关系被删除,则 12345 的 ID 有资格被未来节点或关系。我认为明智的做法是假设新可用的 id 将在未来的某个时候被重用。这有 Neo4j 内部 id 不被认为是“稳定”的负面影响,不应在您的应用程序之外使用。
关于新代理键的示例,我会向您指出位于 https://github.com/graphaware/neo4j-uuid 的 GraphAware 的 neo4j-uuid 项目。此 Neo4j 插件可用于在所有节点和关系上自动创建一个唯一且稳定的 UUID,该 UUID 不会也不能更改或更新。
关于如何回收 Neo4j 内部 ID,Eric 所说的是正确的。
我们已经开始添加对 SDN 的支持,以帮助开发人员解决这个问题。我们可以通过几个例子来做到这一点。
示例 1:当您拥有自然 ID 时
假设我们有一个 User
域对象,它可以由一个名为 email
的字段唯一标识。我们可以这样设置我们的模型:
@NodeEntity
public class User {
@GraphId
private Long id;
@Index(unique=true, primary=true)
private String email;
...
}
然后我们可以这样设置存储库:
public interface UserRepository extends CrudRepository<User, String> {
}
注意参数化类型中的最后一个值是一个字符串。这表示用于此 class.
的主索引
您现在可以执行以下操作:
User user = userRepository.findOne("john.doe@email.com");
了解如何只传递 class 的主要 ID?
示例 2:当您需要合成 ID 时
假设我们上面定义的用户有推文。由于推文没有自然 ID,我们给它一个。避免 ID 冲突的最佳方法是使用类型 4 UUID。幸运的是 Java 预装了 UUID,SDN 支持它的持久性。
import org.neo4j.ogm.annotation.typeconversion.Convert;
import org.neo4j.ogm.typeconversion.UuidStringConverter;
import java.util.UUID;
@NodeEntity
public class Tweet {
@GraphId
private Long id;
@Convert(UuidStringConverter.class)
@Index(unique = true, primary = true)
private UUID uuid;
...
public Tweet(String message) {
this.uuid = UUID.randomUUID();
// other initialisation.
}
}
所以我们这里有一个 UUID
分配给任何创建的推文。然后可以通过转换器将其保存到数据库中。这样做的好处是不需要安装额外的库。它还保证(好吧,在大多数情况下!)永远不会出现内部 Neo4j ID 所具有的问题。优点(或缺点)是 ID 由您的应用程序代码制造为普遍唯一。
如果您希望数据库始终生成 UUID,那么我还推荐 GraphAware https://github.com/graphaware/neo4j-uuid 插件。
Tweet 存储库可以再次利用这一点:
public interface TweetRepository extends CrudRepository<Tweet, UUID> {
}
您现在可以执行以下操作:
Tweet tweet = tweetRepository.findOne(UUID.fromString("0f6e7004-cefc-4397-b4d2-078c1370856a"));
最后一点;在撰写本文时,@Indexed(unique=true,primary=true)
可能会更改为在 SDN 5.0 中简称为 @Id
。
我读到将 Neo4j 内部 ID 用于外部目的不是一个好的做法。
我认为我的 SDN4/Neo4j 应用程序出错了,因为我到处都在使用内部 ID。
我的应用程序中的每个 SDN 4 节点实体都有以下 属性:
@GraphId
private Long id;
我将这个长值用作我的 Web 应用程序 URL 的一部分。例如
/products/3245234
其中 3245234
是此产品节点实体的内部 Neo4j 标识符。
从 Neo4j 的角度来看是否安全 - 以这种方式使用内部 ID?如果不是,能否提供一个新代理键如何解决此问题的示例。
从应用程序的角度来看,使用 Neo4j 内部 ID 是安全的,因为使用它们不会破坏应用程序中的任何内容。
也就是说,Neo4j 的内部 ID 被回收了,我的意思是,如果一个节点或关系的内部 ID 为 12345,并且在某个时候该节点或关系被删除,则 12345 的 ID 有资格被未来节点或关系。我认为明智的做法是假设新可用的 id 将在未来的某个时候被重用。这有 Neo4j 内部 id 不被认为是“稳定”的负面影响,不应在您的应用程序之外使用。
关于新代理键的示例,我会向您指出位于 https://github.com/graphaware/neo4j-uuid 的 GraphAware 的 neo4j-uuid 项目。此 Neo4j 插件可用于在所有节点和关系上自动创建一个唯一且稳定的 UUID,该 UUID 不会也不能更改或更新。
关于如何回收 Neo4j 内部 ID,Eric 所说的是正确的。
我们已经开始添加对 SDN 的支持,以帮助开发人员解决这个问题。我们可以通过几个例子来做到这一点。
示例 1:当您拥有自然 ID 时
假设我们有一个 User
域对象,它可以由一个名为 email
的字段唯一标识。我们可以这样设置我们的模型:
@NodeEntity
public class User {
@GraphId
private Long id;
@Index(unique=true, primary=true)
private String email;
...
}
然后我们可以这样设置存储库:
public interface UserRepository extends CrudRepository<User, String> {
}
注意参数化类型中的最后一个值是一个字符串。这表示用于此 class.
的主索引您现在可以执行以下操作:
User user = userRepository.findOne("john.doe@email.com");
了解如何只传递 class 的主要 ID?
示例 2:当您需要合成 ID 时
假设我们上面定义的用户有推文。由于推文没有自然 ID,我们给它一个。避免 ID 冲突的最佳方法是使用类型 4 UUID。幸运的是 Java 预装了 UUID,SDN 支持它的持久性。
import org.neo4j.ogm.annotation.typeconversion.Convert;
import org.neo4j.ogm.typeconversion.UuidStringConverter;
import java.util.UUID;
@NodeEntity
public class Tweet {
@GraphId
private Long id;
@Convert(UuidStringConverter.class)
@Index(unique = true, primary = true)
private UUID uuid;
...
public Tweet(String message) {
this.uuid = UUID.randomUUID();
// other initialisation.
}
}
所以我们这里有一个 UUID
分配给任何创建的推文。然后可以通过转换器将其保存到数据库中。这样做的好处是不需要安装额外的库。它还保证(好吧,在大多数情况下!)永远不会出现内部 Neo4j ID 所具有的问题。优点(或缺点)是 ID 由您的应用程序代码制造为普遍唯一。
如果您希望数据库始终生成 UUID,那么我还推荐 GraphAware https://github.com/graphaware/neo4j-uuid 插件。
Tweet 存储库可以再次利用这一点:
public interface TweetRepository extends CrudRepository<Tweet, UUID> {
}
您现在可以执行以下操作:
Tweet tweet = tweetRepository.findOne(UUID.fromString("0f6e7004-cefc-4397-b4d2-078c1370856a"));
最后一点;在撰写本文时,@Indexed(unique=true,primary=true)
可能会更改为在 SDN 5.0 中简称为 @Id
。