Neo4jclient - вставка нескольких связей в один пакет
У меня есть сценарий использования, когда я создаю новые отношения каждый раз, когда пользователь видит фотографию, подобную этой:
var dateParams = new { Date = DateTime.Now.ToString() };
graphClient.Cypher
.Match("(user:User), (photo:Photo)")
.Where((UserEntity user) => user.Id == userId)
.AndWhere((PhotoEntity photo) => photo.Id == photoId)
.CreateUnique("user-[:USER_SEEN_PHOTO {params}]->photo")
.WithParam("params", dateParams)
.ExecuteWithoutResults();
Со многими одновременными пользователями это случается очень-очень часто, поэтому мне нужно иметь возможность ставить в очередь ряд операций записи и выполнять их одновременно. К сожалению, я не смог найти хорошую информацию о том, как сделать это наиболее эффективным способом с Neo4jClient, поэтому все предложения будут очень благодарны:)
--- ОБНОВИТЬ ---
Поэтому я пробовал разные комбинации, но все еще не нашел ничего, что работает. Приведенный ниже запрос дает мне "PatternException: Unbound pattern!"?
var query = graphClient.Cypher;
for (int i = 0; i < seenPhotosList.Count; i++)
{
query = query.CreateUnique("(user" + i + ":User {Id : {userId" + i + "} })-[:USER_SEEN_PHOTO]->(photo" + i + ":Photo {Id : {photoId" + i + "} })")
.WithParam("userId" + i, seenPhotosList[i].UserId)
.WithParam("photoId" + i, seenPhotosList[i].PhotoId);
}
query.ExecuteWithoutResults();
Я также попытался изменить CreateUnique на Merge, и этот запрос выполняется без исключения, но создает ли новые узлы вместо того, чтобы соединять существующие?
var query = graphClient.Cypher;
for (int i = 0; i < seenPhotosList.Count; i++)
{
query = query.Merge("(user" + i + ":User {Id : {userId" + i + "} })-[:USER_SEEN_PHOTO]->(photo" + i + ":Photo {Id : {photoId" + i + "} })")
.WithParam("userId" + i, seenPhotosList[i].UserId)
.WithParam("photoId" + i, seenPhotosList[i].PhotoId);
}
query.ExecuteWithoutResults();
2 ответа
Я установил 5 типов отношений с помощью Batch Insert. Он работает очень быстро, но не уверен, как вы будете управлять прерываниями в многопользовательской среде. Вам нужно заранее знать ID узла, а затем создать строку для запроса API, которая выглядит следующим образом...
[{"method":"POST","to":"/node/222/relationships","id":222,"body":{"to":"26045","type":"mother"}},
{"method":"POST","to":"/node/291/relationships","id":291,"body":{"to":"26046","type":"mother"}},
{"method":"POST","to":"/node/389/relationships","id":389,"body":{"to":"26047","type":"mother"}},
{"method":"POST","to":"/node/1031/relationships","id":1031,"body":{"to":"1030","type":"wife"}},
{"method":"POST","to":"/node/1030/relationships","id":1030,"body":{"to":"1031","type":"husband"}},
{"method":"POST","to":"/node/1034/relationships","id":1034,"body":{"to":"26841","type":"father"}},
{"method":"POST","to":"/node/34980/relationships","id":34980,"body":{"to":"26042","type":"child"}}]
Я также разбил это на итеративные запросы разумного размера, чтобы избежать проблем с памятью. Но итерации выполняются очень быстро для настройки необходимых строк. Для получения идентификаторов узлов также требовались итерации, поскольку Neo4j ограничивает число возвращаемых узлов до 1000. Это недостаток Neo4j, который был разработан на основе проблем визуализации (кто может изучать картинку с 10000 узлами?), А не проблем кодирования, таких как те, которые мы обсуждаем,
Я не верю, что Neo4j/cypher имеет какой-либо встроенный способ выполнения того, что вы просите. То, что вы могли бы сделать, это построить что-то, что делает это для вас с системой очередей. Вот запись в блоге о том, как делать масштабируемые записи в Ruby, и это то, что вы могли бы реализовать на своем языке для обработки пакетных вставок / обновлений.