Я играл с набором данных, в котором есть расписание для национальной железной дороги в Великобритании, и они дают вам время отправления и прибытия каждого поезда в текстовом формате.
Например, узел для представления остановки может быть создан следующим образом:
|
1
|
CREATE (stop:Stop {arrival: "0802", departure: "0803H"}) |
Этот формат времени не подходит для запросов, поэтому я хотел добавить еще одно свойство, которое указывало бы количество секунд с начала дня.
Поэтому мы хотим добавить в наш узел свойства прибытие-события-синг-старта и день вылета. Я написал следующий запрос, чтобы вычислить значения для этих свойств.
|
01
02
03
04
05
06
07
08
09
10
11
|
MATCH (stop:Stop)UNWIND ["arrival", "departure"] AS key WITH key, toInteger(substring(stop[key], 0, 2)) AS hours, toInteger(substring(stop[key], 2, 2)) AS minutes, CASE WHEN substring(stop[key], 4,1) = "H" THEN 30 ELSE 0 END AS seconds WITH key, (hours * 60 * 60) + (minutes * 60) + seconds AS secondsSinceStartOfDay RETURN key + "SecondsSinceStartOfDay" AS newKey, secondsSinceStartOfDay |
|
1
2
3
4
5
6
7
|
╒═══════════════════════════════╤══════════════════════╕│newKey │secondsSinceStartOfDay│╞═══════════════════════════════╪══════════════════════╡│arrivalSecondsSinceStartOfDay │28920 │├───────────────────────────────┼──────────────────────┤│departureSecondsSinceStartOfDay│29010 │└───────────────────────────────┴──────────────────────┘ |
Теперь мы готовы установить эти свойства на узле «стоп».
|
01
02
03
04
05
06
07
08
09
10
11
12
|
MATCH (stop:Stop2)UNWIND ["arrival", "departure"] AS key WITH stop, key, toInteger(substring(stop[key], 0, 2)) AS hours, toInteger(substring(stop[key], 2, 2)) AS minutes, CASE WHEN substring(stop[key], 4,1) = "H" THEN 30 ELSE 0 END AS seconds WITH stop, key, (hours * 60 * 60) + (minutes * 60) + seconds AS secondsSinceStartOfDayWITH stop, key + "SecondsSinceStartOfDay" AS newKey, secondsSinceStartOfDaySET stop[newKey] = secondsSinceStartOfDay |
|
1
2
3
|
Invalid input '[': expected an identifier character, whitespace, '{', node labels, a property map, a relationship pattern, '.', '(', '=' or "+=" (line 12, column 9 (offset: 447))"SET stop[newKey] = secondsSinceStartOfDay" ^ |
Хм, это не сработало, как ожидалось! Похоже, мы пока не можем установить динамические свойства, используя Cypher.
К счастью, мой коллега Майкл Хангер и сообщество Neo4j курировали библиотеку процедур APOC, и у нее есть только процедура, которая нам поможет.
Вам нужно скачать jar для вашей версии Neo4j и затем поместить его в каталог плагинов . Я использую Neo4j 3.1 Beta1, так что для меня это выглядит так:
|
1
2
3
4
5
6
|
$ tree neo4j-enterprise-3.1.0-BETA1/plugins/ neo4j-enterprise-3.1.0-BETA1/plugins/└── apoc-3.1.0.1-all.jar 0 directories, 1 file |
После этого вам нужно будет перезапустить Neo4j, чтобы он мог выбрать новые процедуры, которые мы добавили. После этого выполните следующий запрос, чтобы убедиться, что они установлены правильно:
|
1
2
3
4
5
|
call dbms.procedures()YIELD name WITH name WHERE name STARTS WITH "apoc"RETURN COUNT(*) |
|
1
2
3
4
5
|
╒════════╕│COUNT(*)│╞════════╡│183 │└────────┘ |
Теперь мы готовы динамически устанавливать свойства на графике. Процедура, которую мы будем использовать, это apoc.create.setProperty, и наш запрос легко обновить, чтобы использовать его:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
MATCH (stop:Stop)UNWIND ["arrival", "departure"] AS key WITH stop, key, toInteger(substring(stop[key], 0, 2)) AS hours, toInteger(substring(stop[key], 2, 2)) AS minutes, CASE WHEN substring(stop[key], 4,1) = "H" THEN 30 ELSE 0 END AS seconds WITH stop, key, (hours * 60 * 60) + (minutes * 60) + seconds AS secondsSinceStartOfDayWITH stop, key + "SecondsSinceStartOfDay" AS newKey, secondsSinceStartOfDayCALL apoc.create.setProperty(stop, newKey, secondsSinceStartOfDay) |
|
1
2
3
|
Query cannot conclude with CALL (must be RETURN or an update clause) (line 12, column 1 (offset: 439))"CALL apoc.create.setProperty(stop, newKey, secondsSinceStartOfDay)" ^ |
Ой, я говорил слишком рано! Нам нужно получить возвращаемый столбец процедуры и вернуть его или просто вернуть счетчик, чтобы обойти это:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
MATCH (stop:Stop)UNWIND ["arrival", "departure"] AS key WITH stop, key, toInteger(substring(stop[key], 0, 2)) AS hours, toInteger(substring(stop[key], 2, 2)) AS minutes, CASE WHEN substring(stop[key], 4,1) = "H" THEN 30 ELSE 0 END AS seconds WITH stop, key, (hours * 60 * 60) + (minutes * 60) + seconds AS secondsSinceStartOfDayWITH stop, key + "SecondsSinceStartOfDay" AS newKey, secondsSinceStartOfDayCALL apoc.create.setProperty(stop, newKey, secondsSinceStartOfDay) YIELD nodeRETURN COUNT(*) |
|
1
2
3
4
5
|
╒════════╕│COUNT(*)│╞════════╡│2 │└────────┘ |
И это все, теперь мы можем динамически устанавливать свойства в наших запросах.
| Ссылка: | Neo4j: динамически добавлять свойство / задавать динамическое свойство от нашего партнера по JCG Марка Нидхэма в блоге Марка Нидхэма . |