Самый простой способ импортировать простой CSV-файл в граф с помощью OrientDB ETL
Я хотел бы импортировать очень простой файл ориентированного графа в CSV в OrientDB. Конкретно, файл представляет собой набор данных roadNet-PA из коллекции SNAP https://snap.stanford.edu/data/roadNet-PA.html. Первые строки файла следующие:
# Directed graph (each unordered pair of nodes is saved once)
# Pennsylvania road network
# Nodes: 1088092 Edges: 3083796
# FromNodeId ToNodeId
0 1
0 6309
0 6353
1 0
6353 0
6353 6354
Существует только один тип вершин (пересечение дорог), и у ребер нет информации (я полагаю, что легкие ребра OrientDB - лучший вариант для этого). Также обратите внимание, что вершины разделены вкладками.
Я попытался создать простой etl для импорта файла, но безуспешно. Вот этл:
{
"config": {
"log": "debug"
},
"source" : {
"file": { "path": "/tmp/roadNet-PA.csv" }
},
"extractor": { "row": {} },
"transformers": [
{ "csv": { "separator": " ", "skipFrom": 1, "skipTo": 4 } },
{ "vertex": { "class": "Intersection" } },
{ "edge": { "class": "Road" } }
],
"loader": {
"orientdb": {
"dbURL": "remote:localhost/roads",
"dbType": "graph",
"classes": [
{"name": "Intersection", "extends": "V"},
{"name": "Road", "extends": "E"}
], "indexes": [
{"class":"Intersection", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}
Etl работает, но он не импортирует файл, как я ожидаю. Я полагаю, проблема в трансформаторах. Моя идея состоит в том, чтобы читать csv построчно и создавать и ребро, соединяющее обе вершины, но я не уверен, как это выразить в файле etl. Есть идеи?
2 ответа
Попробуй это:
{
"config": {
"log": "debug"
},
"source" : {
"file": { "path": "/tmp/roadNet-PA.csv" }
},
"extractor": { "row": {} },
"transformers": [
{ "csv": { "separator": "\t", "skipFrom": 1, "skipTo": 4,
"columnsOnFirstLine": false,
"columns":["id", "to"] } },
{ "vertex": { "class": "Intersection" } },
{ "merge": { "joinFieldName":"id", "lookup":"Intersection.id" } },
{ "edge": {
"class": "Road",
"joinFieldName": "to",
"lookup": "Intersection.id",
"unresolvedLinkAction": "CREATE"
}
},
],
"loader": {
"orientdb": {
"dbURL": "remote:localhost/roads",
"dbType": "graph",
"wal": false,
"batchCommit": 1000,
"tx": true,
"txUseLog": false,
"useLightweightEdges" : true,
"classes": [
{"name": "Intersection", "extends": "V"},
{"name": "Road", "extends": "E"}
], "indexes": [
{"class":"Intersection", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}
Для ускорения загрузки я предлагаю вам выключить сервер и импортировать ETL, используя "plocal:" вместо "remote:". Пример замены существующего на:
"dbURL": "plocal:/orientdb/databases/roads",
Наконец-то это сработало. Я перенес слияние до вершинной линии, как предложил Лука. Я также изменил поле 'id' на 'from', чтобы избежать ошибки "ключ свойства зарезервирован для всех элементов id". Вот фрагмент:
{
"config": {
"log": "debug"
},
"source" : {
"file": { "path": "/tmp/roads.csv" }
},
"extractor": { "row": {} },
"transformers": [
{ "csv": { "separator": "\t",
"columnsOnFirstLine": false,
"columns":["from", "to"] } },
{ "merge": { "joinFieldName":"from", "lookup":"Intersection.from" } },
{ "vertex": { "class": "Intersection" } },
{ "edge": {
"class": "Road",
"joinFieldName": "to",
"lookup": "Intersection.from",
"unresolvedLinkAction": "CREATE"
}
},
],
"loader": {
"orientdb": {
"dbURL": "remote:localhost/roads",
"dbType": "graph",
"wal": false,
"batchCommit": 1000,
"tx": true,
"txUseLog": false,
"useLightweightEdges" : true,
"classes": [
{"name": "Intersection", "extends": "V"},
{"name": "Road", "extends": "E"}
], "indexes": [
{"class":"Intersection", "fields":["from:integer"], "type":"UNIQUE" }
]
}
}
}