В конце февраля мы взглянули на пакетный импортер Майкла Хангера . Это отличный инструмент для быстрой загрузки миллионов узлов и связей в Neo4j. Единственное, чего не хватало, это индексирования … Я говорю, потому что я только что отправил запрос на добавление, чтобы добавить эту функцию. Давайте рассмотрим, как это было сделано, чтобы вы получили представление о том, как выглядит API пакетного импорта Neo4j, и в следующей статье блога я покажу вам, как генерировать данные, чтобы использовать их в своих интересах.
Первым делом мне нужно было обновить файл pom.xml, включив в него последнюю версию Neo4j и зависимость от индекса Lucene.
<dependency> <groupId>org.neo4j</groupId> <artifactId>neo4j-kernel</artifactId> <version>1.8.M05</version> </dependency> <dependency> <groupId>org.neo4j</groupId> <artifactId>neo4j-lucene-index</artifactId> <version>1.8.M05</version> </dependency>
Функция пакетной вставки была перемещена в org.neo4j.unsafe, чтобы напомнить вам, что ее следует использовать только при первой загрузке.
import org.neo4j.unsafe.batchinsert.BatchInserter; import org.neo4j.unsafe.batchinsert.BatchInserters; import org.neo4j.unsafe.batchinsert.BatchInserterImpl; import org.neo4j.unsafe.batchinsert.BatchInserterIndexProvider; import org.neo4j.unsafe.batchinsert.BatchInserterIndex; import org.neo4j.unsafe.batchinsert.LuceneBatchInserterIndexProvider;
Мы создаем LuceneBatchInserterIndexProvider с именем lucene из БД:
db = BatchInserters.inserter(graphDb.getAbsolutePath(), config); lucene = new LuceneBatchInserterIndexProvider(db);
Давайте посмотрим на метод importNodeIndexes:
private void importNodeIndexes(File file, String indexName, String indexType) throws IOException { BatchInserterIndex index; if (indexType.equals("fulltext")) { index = lucene.nodeIndex( indexName, stringMap( "type", "fulltext" ) ); } else { index = lucene.nodeIndex( indexName, EXACT_CONFIG ); } BufferedReader bf = new BufferedReader(new FileReader(file)); final Data data = new Data(bf.readLine(), "\t", 1); Object[] node = new Object[1]; String line; report.reset(); while ((line = bf.readLine()) != null) { final Map<String, Object> properties = map(data.update(line, node)); index.add(id(node[0]), properties); report.dots(); } report.finishImport("Nodes into " + indexName + " Index"); }
Мы передаем переменную indexType, чтобы решить, будет ли этот индекс точным или полнотекстовым. Мы создаем индекс с помощью lucene.nodeIndex. Затем мы читаем значения, которые нужно добавить в наш индекс, из переданного файла. Как только мы фиксируем ключ и значения из нашего файла, мы просто передаем их вместе с идентификатором нашего узла в метод add.
Давайте посмотрим на importRelationshipIndexes:
private void importRelationshipIndexes(File file, String indexName, String indexType) throws IOException { BatchInserterIndex index; if (indexType.equals("fulltext")) { index = lucene.relationshipIndex( indexName, stringMap( "type", "fulltext" ) ); } else { index = lucene.relationshipIndex( indexName, EXACT_CONFIG ); } BufferedReader bf = new BufferedReader(new FileReader(file)); final Data data = new Data(bf.readLine(), "\t", 1); Object[] rel = new Object[1]; String line; report.reset(); while ((line = bf.readLine()) != null) { final Map<String, Object> properties = map(data.update(line, rel)); index.add(id(rel[0]), properties); report.dots(); } report.finishImport("Relationships into " + indexName + " Index"); }
Он практически идентичен, но мы создаем индексы отношений вместо индексов узлов. Наконец, нам нужно отключить Lucene, а также наш график.
private void finish() { lucene.shutdown(); db.shutdown(); report.finish(); }
Вы можете посмотреть полный исходный код по адресу https://github.com/maxdemarzi/batch-import .
Чтобы использовать его, мы добавим четыре аргумента для каждого индекса в командной строке:
Чтобы создать полнотекстовый индекс узлов с именем users, использующий node_index.csv:
node_index users fulltext nodes_index.csv
Чтобы создать точный индекс отношений с именем работал, используя rels_index.csv:
rel_index worked exact rels_index.csv
Пример командной строки:
java -server -Xmx4G -jar ../batch-import/target/batch-import-jar-with-dependencies.jar neo4j/data/graph.db nodes.csv rels.csv node_index users fulltext nodes_index.csv rel_index worked exact rels_index.csv
Мы ожидаем, что node_index.csv будет выглядеть так:
id name language 1 Victor Richards West Frisian 2 Virginia Shaw Korean 3 Lois Simpson Belarusian 4 Randy Bishop Hiri Motu 5 Lori Mendoza Tok Pisin
Мы ожидаем, что rels_index.csv будет выглядеть так:
id property1 property2 0 cwqbnxrv rpyqdwhk 1 qthnrret tzjmmhta 2 dtztaqpy pbmcdqyc
Столбцы id ссылаются на идентификатор узла или отношения. Заголовки — это ключи индекса, а значения в каждой строке — это то, что будет добавлено в индекс для этого ключа.
Следуйте за мной в Твиттере на @maxdemarzi, и вы узнаете, когда будет опубликовано следующее сообщение в блоге, которое использует эти функции.