Как организовать единичную мощность для свойств Vertex, импортированных через CSV в AWS Neptune?
В документации Neptune говорится, что они поддерживают набор свойств "Задать" только для данных свойств, импортированных через CSV, что означает, что вновь появившееся значение свойства не может перезаписать старое значение свойства в той же вершине и в том же свойстве.
Например, если первый импорт CSV
~id,~label,age
Marko,person,29
тогда у Марко день рождения и второй импорт CSV
~id,~label,age
Marko,person,30
Свойство вершины 'marko' age 'будет содержать оба значения возраста, что не кажется полезным.
AWS говорит, что это (свернуть свойства Set to Single cardinality (сохраняя только последнее полученное значение) необходимо выполнить с постобработкой, через обходы Gremlin.
Означает ли это, что должен существовать обход, который непрерывно сканирует вершины с несколькими свойствами (Set) и снова устанавливает свойство с единичным количеством элементов с последним возможным значением? Если так, какой оптимальный запрос Gremlin делает это?
В псевдо-Гремлин я бы представил что-то вроде:
g.V().property(single, properties(*), _.tail())
Есть ли гарантия, что свойства Set-cardinality всегда указаны в порядке прибытия?
Или я совершенно не на том пути.
Любая помощь будет оценена.
Обновление: Таким образом, лучшее, что я смог сделать, до сих пор еще далеко от идеального решения, но оно все равно может пригодиться кому-то, кто на моем месте.
В плане А, если нам случится знать имена свойств и порядок прибытия не имеет значения вообще (просто нужно единичное количество элементов для этих реквизитов), обход для всех вершин может выглядеть примерно так:
g.V().has(${propname}).where(property(single, ${propname}, properties(${propname}).value().order().tail() ) )
План B состоит в том, чтобы собрать новые значения свойств под временными именами свойств в той же самой вершине (например, начиная с _), и пройти через вершины, имеющие такие временные имена свойств, и установить исходные свойства с их хвостовыми значениями с одной мощностью:
g.V().has(${temp_propname}).where(property(single, ${propname}, properties(${temp_propname}).value().order().tail() ) ).properties('temp_propname').drop()
План C, который был бы самым крутым, но, к сожалению, не работает, состоит в том, чтобы продолжать собирать значения свойств в выделенной вершине, с отметками времени эпохи в качестве имен свойств и значений свойств в качестве их значений:
g.V(${vertexid}).out('has_propnames').properties()
==>vp[1542827843->value1]
==>vp[1542827798->value2]
==>vp[1542887080->latestvalue]
и отсортировать имена свойств (ключи), взять последнее и использовать его значение, чтобы поддерживать значение основного свойства вершины актуальным и соответствовать последнему значению:
g.V().has(${propname}).where(out(${has_these_properties}).count().is(gt(0))).where(property(single, ${propname}, out(${has_these_properties}).properties().value( out(${has_these_properties}).properties().keys().order().tail() ) ) )
Похоже, что параметр для value() step должен быть постоянным, он не может использовать результат другого обхода в качестве параметра, поэтому я не мог заставить это работать. Возможно, кто-то с большим опытом Гремлин знает обходной путь для этого.
1 ответ
AWS недавно представила поддержку "единого" количества элементов в загрузчике CSV:https://docs.aws.amazon.com/neptune/latest/userguide/bulk-load-tutorial-format-gremlin.html Так что больше никаких свойств уровня Gremlin необходимо расположение значений.
Вероятно, было бы более производительным читать в файле, из которого вы выполняете массовую загрузку, и устанавливать это свойство, используя идентификатор вершины, а не сканировать вершину с несколькими значениями для этого свойства.
Таким образом, ваш запрос на обновление gremlin будет выглядеть следующим образом.
g.V(${id})
.property(single,${key},${value})
Что касается того, является ли набор гарантированным заказом, я не знаю.:(