private function commit() { if (count($this->batch->getOperations())) { $this->client->commitBatch(); } else { $this->client->endBatch(); } $this->batch = null; }
/** * Load a single line into the batch * * @param string $line * @param Batch $batch * @param integer $lineNum * @param array $nodes * @param array $rels */ protected function loadLine($line, Batch $batch, $lineNum, &$nodes, &$rels) { $descriptorPattern = "/^(\n\t\t\t\\((\\w+)\\)\t # node identifier or relationship start node\n\t\t\t( # next two sub expressions signify a relationship line\n\t\t\t\t-\\[(\\w*):(\\w+)\\] # relationship identifier and type\n\t\t\t\t->\\((\\w+)\\) # relationship end node\n\t\t)?)(\n\t\t\t\\s+(.*) # properties\n\t\t)?/x"; $indexPattern = "/^(\n\t\t\t\\{(\\w+)\\} # index name\n\t\t\t->(\\(|\\[)\t\t\t\t# ( indicates node index, [ indicates relationship index\n\t\t\t\t(\\w+) # node identifier to index\n\t\t\t(\\)|\\]) # must match opening ( or [\n\t\t)(\n\t\t\t\\s+(.*) # keys:values to index\n\t\t)?/x"; $line = trim($line); if (!$line || $line[0] == '#') { return; } $matches = array(); $descriptorMatch = preg_match($descriptorPattern, $line, $matches); if ($descriptorMatch && !empty($matches[3])) { $startNodeId = $matches[2]; $relId = $matches[4]; $type = $matches[5]; $endNodeId = $matches[6]; if (!isset($nodes[$startNodeId]) || !isset($nodes[$endNodeId])) { throw new Exception("Invalid node reference on line {$lineNum}: {$line}"); } else { if (!empty($relId) && isset($rels[$relId])) { throw new Exception("Duplicate relationship on line {$lineNum}: {$line}"); } } $properties = !empty($matches[8]) ? json_decode($matches[8]) : false; $rel = $this->client->makeRelationship(); $rel->setProperties($properties ?: array())->setType($type)->setStartNode($nodes[$startNodeId])->setEndNode($nodes[$endNodeId]); if (!empty($relId)) { $rels[$relId] = $rel; } $batch->save($rel); return; } else { if ($descriptorMatch) { $nodeId = $matches[2]; if (isset($nodes[$nodeId])) { throw new Exception("Duplicate node on line {$lineNum}: {$line}"); } $properties = !empty($matches[7]) ? json_decode($matches[7]) : false; $node = $this->client->makeNode(); $node->setProperties($properties ?: array()); $nodes[$nodeId] = $node; $batch->save($node); return; } } $matches = array(); $indexMatch = preg_match($indexPattern, $line, $matches); if ($indexMatch) { $name = $matches[2]; $openBrace = $matches[3]; $closeBrace = $matches[5]; $entityId = $matches[4]; $properties = !empty($matches[7]) ? json_decode($matches[7]) : false; if ($properties) { $type = null; if ($openBrace == '(' && $closeBrace == ')') { if (!isset($nodes[$entityId])) { throw new Exception("Invalid node reference on line {$lineNum}: {$line}"); } $entity = $nodes[$entityId]; $type = Index::TypeNode; } else { if ($openBrace == '[' && $closeBrace == ']') { if (!isset($rels[$entityId])) { throw new Exception("Invalid relationship reference on line {$lineNum}: {$line}"); } $entity = $rels[$entityId]; $type = Index::TypeRelationship; } } if ($type) { $index = new Index($this->client, $type, $name); foreach ($properties as $key => $value) { $batch->addToIndex($index, $entity, $key, $value); } return; } } } throw new Exception("Cannot parse line {$lineNum}: {$line}"); }
public static function directTransfer(Neo4jConnection $source, Neo4jConnection $target, $readBatchSize, $nodeBatchSize, $relationBatchSize, $ignoredRelationProperties = null, $preserveIds = null, OutputInterface $output = null) { $sepSize = self::SEP_SIZE; $sourceClient = $source->makeClient(); static::writelnInfo(sprintf('Reading from: %s:%d', $source->getHost(), $source->getPort()), $output); static::sepInfo($sepSize, $output); static::writelnInfo(sprintf('Read batch size: %d', $readBatchSize), $output); list($nodeCount, $minNodeId, $maxNodeId) = static::readNodeStats($sourceClient); static::writelnInfo(sprintf('Number of nodes: %d [%d->%d]', $nodeCount, $minNodeId, $maxNodeId), $output); list($relationCount, $minRelationId, $maxRelationId) = static::readRelationStats($sourceClient); static::writelnInfo(sprintf('Number of relations: %d [%d->%d]', $relationCount, $minRelationId, $maxRelationId), $output); static::sepInfo($sepSize, $output); $targetClient = $target->makeClient(); static::writelnInfo(sprintf('Writing to: %s:%d', $target->getHost(), $target->getPort()), $output); static::sepInfo($sepSize, $output); static::writelnInfo(sprintf('Node batch size: %d', $nodeBatchSize), $output); static::writelnInfo(sprintf('Relation batch size: %d', $relationBatchSize), $output); static::sepInfo($sepSize, $output); list($targetRelationCount, $targetMinRelationId, $targetMaxRelationId) = static::readRelationStats($targetClient); static::writelnInfo(sprintf('Removing relations: %d [%d->%d]', $targetRelationCount, $targetMinRelationId, $targetMaxRelationId), $output); list($targetNodeCount, $targetMinNodeId, $targetMaxNodeId) = static::readNodeStats($targetClient); static::writelnInfo(sprintf('Removing nodes: %d [%d->%d]', $targetNodeCount, $targetMinNodeId, $targetMaxNodeId), $output); $targetClient->executeCypherQuery(new Query($targetClient, self::CYPHER_REMOVE_ALL_NODES)); static::sepInfo($sepSize, $output); $nodeIds = array(); static::writelnInfo(sprintf('Node transfer: %d (%d batches of %d)', $nodeCount, ceil($nodeCount / $nodeBatchSize), $nodeBatchSize), $output); static::sepInfo($sepSize, $output); $fromNodeId = 0; $k = 0; $nodesWithAttributesReferringToIds = array(); while (isset($fromNodeId)) { static::writeInfo('*', $output); $k++; if ($k >= $sepSize) { $k = 0; static::writelnInfo('', $output); } $resultSet = static::readNodes($sourceClient, $readBatchSize, $maxNodeId, $fromNodeId); if (empty($resultSet)) { break; } $i = 0; while ($i < count($resultSet)) { $batch = array_slice($resultSet, $i, $nodeBatchSize); list($nodes, $fromNodeId) = static::importNodes($nodeIds, $targetClient, $batch, $nodesWithAttributesReferringToIds, $preserveIds); static::writeInfo('-', $output); $k++; if ($k >= $sepSize) { $k = 0; static::writelnInfo('', $output); } $i += $nodeBatchSize; } } static::writelnInfo(' .', $output); static::sepInfo($sepSize, $output); if (empty($nodesWithAttributesReferringToIds)) { static::writelnInfo('No node(s) with attributes that refer to node IDs.', $output); } else { static::writelnInfo(sprintf('Updating %d node(s) with node IDs attributes', count($nodesWithAttributesReferringToIds)), $output); } static::sepInfo($sepSize, $output); $batch = new Batch($targetClient); foreach ($nodesWithAttributesReferringToIds as $oldNodeId => $attributesReferringToIds) { $newNodeId = $nodeIds[$oldNodeId]; $n = $targetClient->getNode($newNodeId); foreach ($attributesReferringToIds as $attributeName => $oldId) { $newId = isset($nodeIds[$oldId]) ? $nodeIds[$oldId] : null; $n->setProperty($attributeName, $newId); } $batch->save($n); } $batch->commit(); static::writelnInfo(sprintf('Relation transfer: %d (%d batches of %d)', $relationCount, ceil($relationCount / $relationBatchSize), $relationBatchSize), $output); static::sepInfo($sepSize, $output); $fromRelationId = 0; $k = 0; while (isset($fromRelationId)) { static::writeInfo('*', $output); $k++; if ($k >= $sepSize) { $k = 0; static::writelnInfo('', $output); } $resultSet = static::readRelations($sourceClient, $readBatchSize, $maxRelationId, $fromRelationId); if (empty($resultSet)) { break; } $i = 0; while ($i < count($resultSet)) { $batch = array_slice($resultSet, $i, $relationBatchSize); list($relations, $fromRelationId) = static::importRelations($nodeIds, $targetClient, $batch, $ignoredRelationProperties); static::writeInfo('-', $output); $k++; if ($k >= $sepSize) { $k = 0; static::writelnInfo('', $output); } $i += $relationBatchSize; } } static::writelnInfo(' .', $output); static::sepInfo($sepSize, $output); }