/*
* Copyright (c) 2002-2009 "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.lucene;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Test;
import org.neo4j.graphdb.Node;
import org.neo4j.index.IndexHits;
import org.neo4j.index.IndexService;
import org.neo4j.index.Neo4jWithIndexTestCase;
import org.neo4j.kernel.EmbeddedGraphDatabase;
public class TestLuceneIndexingService extends Neo4jWithIndexTestCase
{
@Override
protected IndexService instantiateIndex()
{
return new LuceneIndexService( graphDb() );
}
@Test
public void testSimple()
{
Node node1 = graphDb().createNode();
assertTrue( !index().getNodes( "a_property",
1 ).iterator().hasNext() );
index().index( node1, "a_property", 1 );
IndexHits<Node> hits = index().getNodes( "a_property", 1 );
Iterator<Node> itr = hits.iterator();
assertEquals( node1, itr.next() );
assertEquals( 1, hits.size() );
assertTrue( !itr.hasNext() );
index().removeIndex( node1, "a_property", 1 );
assertTrue( !index().getNodes( "a_property",
1 ).iterator().hasNext() );
index().index( node1, "a_property", 1 );
Node node2 = graphDb().createNode();
index().index( node2, "a_property", 1 );
hits = index().getNodes( "a_property", 1 );
itr = hits.iterator();
assertTrue( itr.next() != null );
assertTrue( itr.next() != null );
assertTrue( !itr.hasNext() );
assertTrue( !itr.hasNext() );
assertEquals( 2, hits.size() );
index().removeIndex( node1, "a_property", 1 );
index().removeIndex( node2, "a_property", 1 );
assertTrue( !index().getNodes( "a_property",
1 ).iterator().hasNext() );
itr = index().getNodes( "a_property", 1 ).iterator();
assertTrue( !itr.hasNext() );
restartTx();
node1.delete();
node2.delete();
}
@Test
public void testMultipleAdd()
{
Node node = graphDb().createNode();
index().index( node, "a_property", 3 );
restartTx();
index().index( node, "a_property", 3 );
restartTx();
index().removeIndex( node, "a_property", 3 );
restartTx();
assertTrue( index().getSingleNode( "a_property", 3 ) == null );
}
@Test
public void testCaching()
{
String key = "prop";
Object value = 10;
assertNull( ( (LuceneIndexService) index() ).getEnabledCacheSize( key ) );
( ( LuceneIndexService ) index() ).enableCache( key, 1000 );
assertEquals( ( Integer ) 1000,
( (LuceneIndexService) index() ).getEnabledCacheSize( key ) );
Node node1 = graphDb().createNode();
index().index( node1, key, value );
index().getNodes( key, value );
restartTx( false );
Node node2 = graphDb().createNode();
index().getNodes( key, value );
index().index( node2, key, value );
index().getNodes( key, value );
restartTx();
Node node3 = graphDb().createNode();
index().getNodes( key, value );
index().index( node3, key, value );
index().getNodes( key, value );
restartTx( false );
Node node4 = graphDb().createNode();
index().getNodes( key, value );
index().index( node4, key, value );
index().getNodes( key, value );
restartTx();
assertCollection( asCollection( index().getNodes( key, value ) ),
node2, node4 );
index().removeIndex( node2, key, value );
index().removeIndex( node4, key, value );
node2.delete();
node4.delete();
}
@Test
public void testRollback()
{
Node node1 = graphDb().createNode();
Node node2 = graphDb().createNode();
restartTx();
index().index( node1, "a_property", 3 );
assertEquals( node1, index().getSingleNode( "a_property", 3 ) );
restartTx( false );
assertEquals( null, index().getSingleNode( "a_property", 3 ) );
index().index( node2, "a_property", 3 );
assertEquals( node2, index().getSingleNode( "a_property", 3 ) );
restartTx();
assertEquals( node2, index().getSingleNode( "a_property", 3 ) );
}
@Test
public void testDoubleIndexing() throws Exception
{
Node node = graphDb().createNode();
index().index( node, "double", "value" );
restartTx();
index().index( node, "double", "value" );
restartTx();
Set<Node> hits = new HashSet<Node>();
for ( Node hit : index().getNodes( "double", "value" ) )
{
assertTrue( hits.add( hit ) );
}
node.delete();
}
@Test
@Ignore
public void testChangeValueBug() throws Exception
{
Node andy = graphDb().createNode();
Node larry = graphDb().createNode();
andy.setProperty( "name", "Andy Wachowski" );
andy.setProperty( "title", "Director" );
// Deliberately set Larry's name wrong
larry.setProperty( "name", "Andy Wachowski" );
larry.setProperty( "title", "Director" );
index().index( andy, "name", andy.getProperty( "name" ) );
index().index( andy, "title", andy.getProperty( "title" ) );
index().index( larry, "name", larry.getProperty( "name" ) );
index().index( larry, "title", larry.getProperty( "title" ) );
// Correct Larry's name
index().removeIndex( larry, "name",
larry.getProperty( "name" ) );
larry.setProperty( "name", "Larry Wachowski" );
index().index( larry, "name",
larry.getProperty( "name" ) );
assertCollection( asCollection( index().getNodes(
"name", "Andy Wachowski" ) ), andy );
assertCollection( asCollection( index().getNodes(
"name", "Larry Wachowski" ) ), larry );
}
@Test
public void testGetNodesBug() throws Exception
{
Node node1 = graphDb().createNode();
Node node2 = graphDb().createNode();
String key = "getnodesbug";
( ( LuceneIndexService ) index() ).enableCache( key, 100 );
index().index( node1, key, "value" );
index().index( node2, key, "value" );
restartTx();
assertCollection( asCollection(
index().getNodes( key, "value" ) ), node1, node2 );
// Now that value is cached
index().removeIndex( node1, key, "value" );
assertCollection( asCollection(
index().getNodes( key, "value" ) ), node2 );
index().removeIndex( node2, key, "value" );
node1.delete();
node2.delete();
}
@Test
public void testRemoveAll() throws Exception
{
Node node1 = graphDb().createNode();
Node node2 = graphDb().createNode();
String key = "removeall";
index().index( node1, key, "value1" );
index().index( node1, key, "value2" );
index().index( node2, key, "value1" );
index().index( node2, key, "value2" );
restartTx();
assertCollection( asCollection(
index().getNodes( key, "value1" ) ), node1, node2 );
index().removeIndex( node1, key );
index().index( node1, key, "value2" );
assertCollection( asCollection(
index().getNodes( key, "value1" ) ), node2 );
assertCollection( asCollection(
index().getNodes( key, "value2" ) ), node1, node2 );
index().index( node1, key, "value1" );
restartTx();
index().removeIndex( key );
assertCollection( asCollection(
index().getNodes( key, "value2" ) ) );
index().index( node1, key, "value1" );
index().index( node2, key, "value2" );
assertCollection( asCollection(
index().getNodes( key, "value1" ) ), node1 );
restartTx();
index().removeIndex( key );
assertCollection( asCollection(
index().getNodes( key, "value1" ) ) );
assertCollection( asCollection(
index().getNodes( key, "value2" ) ) );
node2.delete();
node1.delete();
}
@Test
public void testRemoveAllWithCache() throws Exception
{
Node node1 = graphDb().createNode();
String key = "removeallc";
( (LuceneIndexService) index() ).enableCache( key, 1000 );
index().index( node1, key, "value1" );
index().index( node1, key, "value2" );
restartTx();
assertEquals( node1, index().getSingleNode( key, "value1" ) );
assertEquals( node1, index().getSingleNode( key, "value2" ) );
index().removeIndex( node1, key );
assertNull( index().getSingleNode( key, "value1" ) );
assertNull( index().getSingleNode( key, "value2" ) );
restartTx();
assertNull( index().getSingleNode( key, "value1" ) );
assertNull( index().getSingleNode( key, "value2" ) );
node1.delete();
}
@Test
public void testIndexLargeString() throws Exception
{
Node node1 = graphDb().createNode();
byte[] data = new byte[10*1024*1024];
String value = new String( data );
index().index( node1, "large_string", value );
restartTx();
// this will not work
// assertEquals( node1,
// index().getSingleNode( "large_string", value ) );
index().removeIndex( node1, "large_string" );
node1.delete();
}
@Ignore
@Test
public void testDifferentTypesWithSameValueIssue()
{
String key = "prop";
Integer valueAsInt = 10;
String valueAsString = "10";
Node node1 = graphDb().createNode();
index().index( node1, key, valueAsInt );
Node node2 = graphDb().createNode();
index().index( node2, key, valueAsString );
assertCollection( index().getNodes( key, valueAsInt ), node1 );
assertCollection( index().getNodes( key, valueAsString ), node2 );
restartTx();
assertCollection( index().getNodes( key, valueAsInt ), node1 );
assertCollection( index().getNodes( key, valueAsString ), node2 );
index().removeIndex( node1, key, valueAsInt );
index().removeIndex( node2, key, valueAsString );
node2.delete();
node1.delete();
}
@Ignore
@Test
public void testInsertionSpeed()
{
Node node = graphDb().createNode();
long t = System.currentTimeMillis();
for ( int i = 0; i < 5000000; i++ )
{
index().index( node, "yeah", "value" + i );
if ( i % 100000 == 0 )
{
restartTx();
System.out.print( "." );
}
}
finishTx( true );
System.out.println( "insert:" + (System.currentTimeMillis() - t) );
t = System.currentTimeMillis();
for ( int i = 0; i < 100; i++ )
{
for ( Node n : index().getNodes( "yeah", "value" + i ) )
{
}
}
System.out.println( "get:" + (System.currentTimeMillis() - t) );
}
@Test
public void testArrayProperties()
{
Node node = graphDb().createNode();
int[] integers = new int[] { 10, 1034, 4321 };
String[] strings = new String[] { "Array strings can be indexed",
"It is a more expected behaviour",
"Than not to" };
index().index( node, "integer", integers );
index().index( node, "string", strings );
assertEquals( node, index().getSingleNode( "integer", 1034 ) );
assertNull( index().getSingleNode( "integer", 111111 ) );
assertEquals( node, index().getSingleNode( "string", strings[0] ) );
assertEquals( node, index().getSingleNode( "string", strings[1] ) );
assertEquals( node, index().getSingleNode( "string", strings[2] ) );
assertNull( index().getSingleNode( "string", "Something else" ) );
restartTx();
assertEquals( node, index().getSingleNode( "integer", 1034 ) );
assertNull( index().getSingleNode( "integer", 111111 ) );
assertEquals( node, index().getSingleNode( "string", strings[0] ) );
assertEquals( node, index().getSingleNode( "string", strings[1] ) );
assertEquals( node, index().getSingleNode( "string", strings[2] ) );
assertNull( index().getSingleNode( "string", "Something else" ) );
index().removeIndex( node, "integer", integers );
index().removeIndex( node, "string", strings );
assertNull( index().getSingleNode( "integer", 1034 ) );
assertNull( index().getSingleNode( "string", strings[1] ) );
node.delete();
}
@Test
public void testReadWithoutTx()
{
Node node1 = graphDb().createNode();
Node node2 = graphDb().createNode();
index().index( node1, "wo-tx", "value1" );
index().index( node2, "wo-tx", "value2" );
finishTx( true );
assertEquals( node1, index().getSingleNode( "wo-tx", "value1" ) );
assertEquals( node2, index().getSingleNode( "wo-tx", "value2" ) );
assertCollection( index().getNodes( "wo-tx", "value1" ), node1 );
assertCollection( index().getNodes( "wo-tx", "value2" ), node2 );
beginTx();
index().removeIndex( "wo-tx" );
node1.delete();
node2.delete();
}
protected String dirName()
{
return "lucene";
}
@Test
public void makeSureDirectoryIsRemovedInRemoveAll()
{
Node node = graphDb().createNode();
String key = "delall";
index().index( node, key, "value" );
restartTx();
File dir = new File( new File( new File(
( (EmbeddedGraphDatabase) graphDb() ).getStoreDir() ), dirName() ), key );
assertTrue( dir.exists() );
index().removeIndex( key );
restartTx();
assertFalse( dir.exists() );
}
}