/** * Copyright (c) 2002-2011 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.index.impl.lucene; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.neo4j.helpers.collection.MapUtil.map; import static org.neo4j.index.Neo4jTestCase.assertContains; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import junit.framework.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.index.BatchInserterIndex; import org.neo4j.graphdb.index.BatchInserterIndexProvider; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.index.IndexManager; import org.neo4j.helpers.collection.IteratorUtil; import org.neo4j.helpers.collection.MapUtil; import org.neo4j.index.Neo4jTestCase; import org.neo4j.kernel.EmbeddedGraphDatabase; import org.neo4j.kernel.impl.batchinsert.BatchInserter; import org.neo4j.kernel.impl.batchinsert.BatchInserterImpl; public class TestLuceneBatchInsert { private static final String PATH = "target/var/batch"; @Before public void cleanDirectory() { Neo4jTestCase.deleteFileOrDirectory( new File( PATH ) ); } @Test public void testSome() throws Exception { BatchInserter inserter = new BatchInserterImpl( PATH ); BatchInserterIndexProvider provider = new LuceneBatchInserterIndexProvider( inserter ); BatchInserterIndex index = provider.nodeIndex( "users", LuceneIndexProvider.EXACT_CONFIG ); Map<Integer, Long> ids = new HashMap<Integer, Long>(); for ( int i = 0; i < 100; i++ ) { long id = inserter.createNode( null ); index.add( id, MapUtil.map( "name", "Joe" + i, "other", "Schmoe" ) ); ids.put( i, id ); } for ( int i = 0; i < 100; i++ ) { assertContains( index.get( "name", "Joe" + i ), ids.get( i ) ); } assertContains( index.query( "name:Joe0 AND other:Schmoe" ), ids.get( 0 ) ); assertContains( index.query( "name", "Joe*" ), ids.values().toArray( new Long[ids.size()] ) ); provider.shutdown(); inserter.shutdown(); GraphDatabaseService db = new EmbeddedGraphDatabase( PATH ); assertTrue( db.index().existsForNodes( "users" ) ); Index<Node> dbIndex = db.index().forNodes( "users" ); for ( int i = 0; i < 100; i++ ) { assertContains( dbIndex.get( "name", "Joe" + i ), db.getNodeById( ids.get( i ) ) ); } Collection<Node> nodes = new ArrayList<Node>(); for ( long id : ids.values() ) { nodes.add( db.getNodeById( id ) ); } assertContains( dbIndex.query( "name", "Joe*" ), nodes.toArray( new Node[nodes.size()] ) ); assertContains( dbIndex.query( "name:Joe0 AND other:Schmoe" ), db.getNodeById( ids.get( 0 ) ) ); db.shutdown(); } @Test public void testFulltext() { BatchInserter inserter = new BatchInserterImpl( PATH ); BatchInserterIndexProvider provider = new LuceneBatchInserterIndexProvider( inserter ); String name = "users"; BatchInserterIndex index = provider.nodeIndex( name, MapUtil.stringMap( "type", "fulltext" ) ); long id1 = inserter.createNode( null ); index.add( id1, MapUtil.map( "name", "Mattias Persson", "email", "something@somewhere", "something", "bad" ) ); long id2 = inserter.createNode( null ); index.add( id2, MapUtil.map( "name", "Lars PerssoN" ) ); index.flush(); assertContains( index.get( "name", "Mattias Persson" ), id1 ); assertContains( index.query( "name", "mattias" ), id1 ); assertContains( index.query( "name", "bla" ) ); assertContains( index.query( "name", "persson" ), id1, id2 ); assertContains( index.query( "email", "*@*" ), id1 ); assertContains( index.get( "something", "bad" ), id1 ); long id3 = inserter.createNode( null ); index.add( id3, MapUtil.map( "name", new String[] { "What Ever", "Anything" } ) ); index.flush(); assertContains( index.get( "name", "What Ever" ), id3 ); assertContains( index.get( "name", "Anything" ), id3 ); provider.shutdown(); inserter.shutdown(); GraphDatabaseService db = new EmbeddedGraphDatabase( PATH ); Index<Node> dbIndex = db.index().forNodes( name ); Node node1 = db.getNodeById( id1 ); Node node2 = db.getNodeById( id2 ); assertContains( dbIndex.query( "name", "persson" ), node1, node2 ); db.shutdown(); } @Ignore @Test public void testInsertionSpeed() { BatchInserter inserter = new BatchInserterImpl( PATH ); BatchInserterIndexProvider provider = new LuceneBatchInserterIndexProvider( inserter ); BatchInserterIndex index = provider.nodeIndex( "yeah", LuceneIndexProvider.EXACT_CONFIG ); index.setCacheCapacity( "key", 1000000 ); long t = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { Map<String, Object> properties = MapUtil.map( "key", "value" + i ); long id = inserter.createNode( properties ); index.add( id, properties ); } System.out.println( "insert:" + ( System.currentTimeMillis() - t ) ); index.flush(); t = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { IteratorUtil.count( (Iterator<Long>) index.get( "key", "value" + i ) ); } System.out.println( "get:" + ( System.currentTimeMillis() - t ) ); } @Test public void testFindCreatedIndex() { String indexName = "persons"; BatchInserter inserter = new BatchInserterImpl( PATH ); LuceneBatchInserterIndexProvider indexProvider = new LuceneBatchInserterIndexProvider( inserter ); BatchInserterIndex persons = indexProvider.nodeIndex( "persons", MapUtil.stringMap( "type", "exact" ) ); Map<String, Object> properties = MapUtil.map( "name", "test" ); long node = inserter.createNode( properties ); persons.add( node, properties ); indexProvider.shutdown(); inserter.shutdown(); GraphDatabaseService graphDb = new EmbeddedGraphDatabase( PATH ); Transaction tx = graphDb.beginTx(); try { IndexManager indexManager = graphDb.index(); Assert.assertFalse( indexManager.existsForRelationships( indexName ) ); Assert.assertTrue( indexManager.existsForNodes( indexName ) ); Assert.assertNotNull( indexManager.forNodes( indexName ) ); Index<Node> nodes = graphDb.index().forNodes( indexName ); Assert.assertTrue( nodes.get( "name", "test" ).hasNext() ); tx.success(); tx.finish(); } finally { graphDb.shutdown(); } } @Test public void testCanIndexRelationships() { BatchInserter inserter = new BatchInserterImpl( PATH ); BatchInserterIndexProvider indexProvider = new LuceneBatchInserterIndexProvider( inserter ); BatchInserterIndex edgesIndex = indexProvider.relationshipIndex( "edgeIndex", MapUtil.stringMap( "provider", "lucene", "type", "exact" ) ); long nodeId1 = inserter.createNode( MapUtil.map( "ID", "1" ) ); long nodeId2 = inserter.createNode( MapUtil.map( "ID", "2" ) ); long relationshipId = inserter.createRelationship( nodeId1, nodeId2, EdgeType.KNOWS, null ); edgesIndex.add( relationshipId, MapUtil.map( "EDGE_TYPE", EdgeType.KNOWS.name() ) ); edgesIndex.flush(); assertEquals( String.format( "Should return relationship id" ), new Long( relationshipId ), edgesIndex.query( "EDGE_TYPE", EdgeType.KNOWS.name() ).getSingle() ); indexProvider.shutdown(); inserter.shutdown(); } @Test public void triggerNPEAfterFlush() { BatchInserter inserter = new BatchInserterImpl( PATH ); BatchInserterIndexProvider provider = new LuceneBatchInserterIndexProvider( inserter ); BatchInserterIndex index = provider.nodeIndex( "Neo4j::Node-exact", LuceneIndexProvider.EXACT_CONFIG ); Map<String, Object> map = map( "name", "Something" ); long node = inserter.createNode( map ); index.add( node, map ); index.flush(); assertContains( index.get( "name", "Something" ), node ); provider.shutdown(); inserter.shutdown(); } private enum EdgeType implements RelationshipType { KNOWS } }