Хранение объекта как свойства в Neo4j

Мне нужно сохранить массив объектов User внутри узла Tile. Каждый объект User содержит три примитивных свойства; Id (одна строка буквенных символов), fName и lName. Этот список объектов является свойством узла Tile с несколькими другими примитивными свойствами. Весь узел Tile должен быть сериализован в Json, включая вложенные объекты User.

Я понимаю, что Neo не может хранить сложные объекты в качестве свойств. Я создал пользователя как отдельный узел с id, fName и lName в качестве свойств, и я могу вернуть их через Cypher. Я также могу получить выходные результаты Json для родительского узла Tile. (В данном случае Users — это просто строка разделенных запятыми альфа-каналов). Но как мне получить вывод пользовательского узла, вложенный в родительский узел?

Я создал список пользовательских объектов (userList), связав пользовательские объекты со строкой идентификаторов пользователей в узле плитки с помощью шифрованного запроса. Мне просто нужно перейти от двух отдельных выходов json к одному вложенному выходу.

Я надеюсь, что это достаточно подробно. Я использую Neo4j 2.1.6 и Neo4jClient. Я также использую .Net 4.0.


person Wayne Cordrey    schedule 12.05.2015    source источник


Ответы (3)


Вы можете сделать что-то подобное с шифром и заставить шифр возвращать составной объект.

MATCH (t:Tile)-[:CONTAINS_USER]-(u:User)
WHERE t.name =~ 'Tile.*'
WITH {name: t.name, users: collect(u) } AS tile
RETURN collect(tile) AS tiles 
person Dave Bennett    schedule 12.05.2015
comment
Ооо, это обман. Мне это нравится. :) - person FrobberOfBits; 13.05.2015
comment
Что мне добавить к этому, чтобы отобразить результаты сбора? - person Wayne Cordrey; 20.05.2015
comment
есть две коллекции: 1) первая часть запроса просто сопоставляет плитки и создает коллекции связанных пользователей. Это возвращается в виде составной карты tile, которая содержит некоторые данные плитки и набор пользователей для этой плитки. 2) просто берет все новые тайловые карты и возвращает их как коллекцию. - person Dave Bennett; 20.05.2015
comment
Ха! Теперь я понимаю! Я проверил это и понял это решение. Я также гораздо яснее понимаю, как использовать отношения. Это ОЧЕНЬ помогает. - person Wayne Cordrey; 20.05.2015

Вы не должны хранить другой объект как вложенное свойство. Как вы правильно заметили, neo4j не поддерживает это, но даже если бы это было так, вам не следует этого делать, потому что вы должны связать их отношениями. Это ключевая сила графовой базы данных, такой как neo4j, поэтому вы должны использовать эту силу и использовать отношения.

Сервер имеет формат JSON по умолчанию, который имеет тенденцию выводить узлы как свои собственные объекты JSON. Это означает, что на практике, поскольку вы собираетесь моделировать это как два отдельных узла с отношениями, вы не можете заставить сервер по умолчанию вкладывать JSON для одного объекта под другим. Он не будет вкладывать JSON таким образом, потому что данные будут храниться иначе.

В этом случае я бы использовал службы REST, чтобы получить JSON для каждого объекта отдельно, а затем самостоятельно выполнить вложение в ваш код — ваш код — единственное место, где вы будете знать, под каким свойством он должен быть вложен, и как это надо сделать.

person FrobberOfBits    schedule 12.05.2015
comment
Я согласен с тем, что вам следует подумать о том, следует ли хранить объект как вложенное свойство, но неверно говорить, что вы не можете сделать это, а также я думаю, что слишком широко говорить, что вы не должны хранить любые объекты как вложенные свойства. Примером может служить что-то вроде даты, мы можем использовать DateTime, но вы также можете разбить его на 3 связанных узла дня, месяца и года, что может быть подходящим или огромным излишеством. - person Charlotte Skardon; 13.05.2015
comment
В итоге я сериализовал этот список пользовательских объектов и поместил его в виде строки в свойство пользователя на узле Tile. Запрос узла плитки выводит действительный вложенный JSON, поэтому я думаю, что я на правильном пути. У меня есть другая ошибка, поэтому трудно сказать наверняка, работает она или нет. Приемлемо ли это как стратегия? Оба ваших ответа были превосходны, вместе они сильнее — отличная командная работа! - person Wayne Cordrey; 13.05.2015
comment
@ChrisSkardon точка зрения принята; конечно, с любой технологией очень мало того, что вы принципиально не можете сделать. И я понимаю то, что вы имеете в виду под DateTime, но это особый случай, обычно рассматриваемый как встроенный примитивный тип, а не как сложный пользовательский тип. Я думал о сложных доменных/определяемых пользователем типах, таких как банковский счет. Могли бы вы это сделать? Ну да... конечно, но трудно представить общие сценарии, в которых это было бы лучшим решением. (Конечно, вы также можете придумать нестандартные ниши, где это может быть предпочтительнее) - person FrobberOfBits; 13.05.2015
comment
@WayneCordrey Я думал, что решение Дэйва Беннета было творческим и аккуратным, мне жаль, что я не подумал об этом. Сериализация в строки может работать в крайнем случае, но если бы это был я, я бы постарался избежать этого, поскольку позже вы получите дополнительную проблему десериализации этих строк обратно в объекты. Не уверен, что понимаю, почему вы просто не используете отдельный узел и отношение, опять же, это то, что будет играть на сильных сторонах используемой вами БД. - person FrobberOfBits; 13.05.2015
comment
@WayneCordrey Поскольку вы используете Neo4jClient, вы можете создать свой собственный сериализатор Json и передать его клиенту, который затем будет использовать его для экземпляров вашего класса (см. stackoverflow.com/questions/23132187/). @FrobberOfBits Я полностью с вами согласен, просто хотел убедиться, что кто-то, у кого есть ниша, не прочитал комментарий, а затем сдался :) - person Charlotte Skardon; 15.05.2015

В дополнение к этим ответам обратите внимание, что если вам не нужно использовать свойства подполя в каком-либо из ваших запросов (например, искать плитки, где имя пользователя равно «X»), вы можете просто сериализовать поля объектов в строку перед вставкой (например, с JSON.stringify) и десериализовать их при чтении из БД.

Это особенно полезно, когда вы хотите «прикрепить» структурированные данные к узлу, но вам не очень важны эти данные в отношении отношений в вашей БД (например, пользовательских настроек).

person Jonathan H    schedule 16.05.2017