埃裏克在談到如何回收Neo4j內部ID的時候說的是正確的。
我們已經開始爲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> {
}
請注意,在參數化類型的最後一個值是怎樣一個字符串。這代表這個類使用的主要索引。
現在你可以這樣做:
User user = userRepository.findOne("[email protected]");
看你怎麼可以只通過在類的主ID?
例2:當你需要一個合成的ID
假設我們上面定義的用戶鳴叫。由於tweet沒有自然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的問題。 pro(或con)是ID的製造是通用的,由您的應用程序代碼獨一無二。
如果您希望讓數據庫始終生成UUID,那麼我還會推薦GraphAware https://github.com/graphaware/neo4j-uuid插件。
再次鳴叫庫可以利用這一點:
public interface TweetRepository extends CrudRepository<Tweet, UUID> {
}
現在你可以這樣做:
Tweet tweet = tweetRepository.findOne(UUID.fromString("0f6e7004-cefc-4397-b4d2-078c1370856a"));
最後需要說明的;在撰寫本文時,SDN 5.0中可能更改爲@Indexed(unique=true,primary=true)
,簡稱爲@Id
。
非常感謝您的詳細解答!關於Cypher查詢和「UUID」的一個後續問題。以前,作爲我的Cypher查詢的一個參數,我使用了'Ids(@GraphId)'和以下語句 - 例如{productIds}中的WHERE ID(p)'。現在,我不得不通過一個集合'UUID'。如何在Cypher中正確使用這些'UUID' - ID(p)IN {productUUIDs}'或simlpe'p IN {productUUs}}。另外,與'GraphId'和'@Index(unique = true,primary = true)private UUID uuid'之間的性能角度有什麼不同? – alexanoid
您應該可以執行類似於'WHERE p.uuid IN {productUuids}'的地方,其中'productUuids'是字符串表示。我不確定目前是否支持存儲庫方法的參數轉換,但是我們將在下一個版本中進行。關於性能,如果你打開autoindexing或者你已經索引了標籤的uuid屬性,那麼它應該非常快,因爲查找是通過索引完成的。 – digx1