Должны ли мы использовать отношения, специфичные для узла, или отношения, не зависящие от узла?

Я пытаюсь подключить различные типы узлов из Spring Data Neo4j. Рекомендуется ли (или не рекомендуется) использовать один и тот же тип связи для аналогичных отношений, связывающих разные типы узлов?

Например, если у нас есть класс Driver (с аннотацией @NodeEntity), и мы хотим смоделировать тот факт, что водитель может управлять разными транспортными средствами, например. Автомобили и мотоциклы, это лучше иметь:

@RelatedTo(elementClass = CarNode.class, type = "drives", direction = OUTGOING)
private Set<Car> cars;

@RelatedTo(elementClass = BikeNode.class, type = "drives", direction = OUTGOING)
private Set<Bike> bikes;

потому что водитель может управлять разными типами транспортных средств, или мы должны указать тип транспортного средства в отношении :

@RelatedTo(elementClass = CarNode.class, type = "drivesCar", direction = OUTGOING)
private Set<Car> cars;

@RelatedTo(elementClass = BikeNode.class, type = "drivesBike", direction = OUTGOING)
private Set<Bike> bikes;

Первая возможность кажется более семантически правильной, но кажется логичным, что использование определенных отношений по всему графу может обеспечить более быстрый обход (нет необходимости тестировать типы узлов).

Если общие отношения лучше, как можно получить только набор автомобилей или только набор велосипедов с помощью запроса Cypher?

Спасибо!


person Grégoire C    schedule 27.11.2013    source источник


Ответы (2)


В целом рекомендуется подробно указывать тип отношений.

Основная причина в том, что ваши запросы станут дешевле. В качестве примера предположим, что вы хотите запросить для данного водителя все велосипеды, на которых он ездил. В случае общего типа отношений drives это разрешается в Cypher следующим образом:

start d=node:driver(name=<driverName>)
match (d)-[:drives]->(vehicle)
where vehicle.__type__ = 'Bike'
return vehicle

Принимая во внимание, что в случае подробных типов отношений:

start d=node:driver(name=<driverName>)
match (d)-[:drivesBike]->(bike)
return bike

Второй дешевле, так как вы не переходите к не-велосипедам. В первом случае вы жадничаете на обход и применяете фильтр.

person Stefan Armbruster    schedule 27.11.2013

Добавление немного к ответу Стефана: вы можете рассмотреть возможность использования как общего drives и более конкретного drivesBike & drivesCar.. Могут быть случаи, когда вы просто хотите получить все транспортные средства, которыми управляет человек, и для этого ... у вас есть drives. Если вам нужны все велосипедисты, то есть drivesBike. Если у вас есть как конкретные, так и общие отношения, вы можете оптимально запрашивать оба способа, и наличие дополнительных отношений на самом деле не влияет на размер вашей базы данных. (хотя это добавляет немного кода, чтобы добавить две связи отношений. Просто помните, что если бы у вас были только определенные отношения драйвера, у вас был бы некоторый тип запроса ИЛИ с вызовом всех типов драйверов, и вы' d необходимо обновлять ваш запрос каждый раз, когда вы добавляете новый тип транспортного средства.В этом случае более удобно иметь общую связь drives.

На самом деле эта идея изложена в книге Графические базы данных. Подробнее об этом шаблоне можно прочитать там.

person David Makogon    schedule 27.11.2013
comment
Если я использую Spring Data Neo4j и аннотацию @RelatedTo, то использование обоих drives и drivesCar невозможно, так как это приведет либо к ошибке Duplicate annotation, либо к дублированию коллекции автомобилей… Это ограничение SDN?… - person Grégoire C; 29.11.2013
comment
Я не знаю о Spring Data для Neo4j, но... вам понадобятся две разные связи между узлами, а не одна связь с двумя типами. И данные Spring, безусловно, должны поддерживать это, поскольку графы часто имеют несколько отношений между узлами. - person David Makogon; 29.11.2013
comment
Вы можете расширять свои классы сущностей графа, чтобы сопоставлять различные значения с одним типом отношений в neo4j. Кстати, если у вас нет конкретных проблем с производительностью, я бы не беспокоился об общем/конкретном, а о реалистичном. Стоимость Computronic — меньшая проблема, специфичная для вашей модели и привычек потребления графа, но головная боль дизайнера / разработчика / пользователя универсальна, поэтому, пока у вас нет веских причин не делать этого, вы должны просто быть реалистом. Я обычно не езжу на велосипеде, но могу водить машину, даже если это велосипед. - person jjaderberg; 04.12.2013
comment
@jjaderberg Я согласен насчет скорости и головной боли. Технически, как вы можете сопоставить разные значения, не используя несколько типов отношений? Означает ли это наличие Bike extends Vehicle с приводами в коллекции транспортных средств? Не могли бы вы добавить новый ответ? Спасибо! - person Grégoire C; 06.12.2013