/* * 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 java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.neo4j.graphdb.Node; import org.neo4j.index.IndexHits; import org.neo4j.index.IndexService; import org.neo4j.index.Isolation; public class TestLuceneFulltextIndexService extends TestLuceneIndexingService { @Override protected IndexService instantiateIndexService() { return new LuceneFulltextIndexService( graphDb() ); } @Override public void testCaching() { // Do nothing } @Override public void testGetNodesBug() { // Do nothing } public void testSimpleFulltext() { Node node1 = graphDb().createNode(); String value1 = "A value with spaces in it which the fulltext " + "index should tokenize"; String value2 = "Another value with spaces in it"; String key = "some_property"; assertTrue( !indexService().getNodes( key, value1 ).iterator().hasNext() ); assertTrue( !indexService().getNodes( key, value2 ).iterator().hasNext() ); indexService().index( node1, key, value1 ); Iterator<Node> itr = indexService().getNodes( key, "fulltext" ).iterator(); assertEquals( node1, itr.next() ); assertTrue( !itr.hasNext() ); indexService().removeIndex( node1, key, value1 ); assertTrue( !indexService().getNodes( key, value1 ).iterator().hasNext() ); indexService().index( node1, key, value1 ); Node node2 = graphDb().createNode(); indexService().index( node2, key, value1 ); restartTx(); IndexHits hits = indexService().getNodes( key, "tokenize" ); itr = hits.iterator(); assertTrue( itr.next() != null ); assertTrue( itr.next() != null ); assertTrue( !itr.hasNext() ); assertTrue( !itr.hasNext() ); assertEquals( 2, hits.size() ); indexService().removeIndex( node1, key, value1 ); indexService().removeIndex( node2, key, value1 ); assertTrue( !indexService().getNodes( key, value1 ).iterator().hasNext() ); itr = indexService().getNodes( key, value1 ).iterator(); assertTrue( !itr.hasNext() ); restartTx(); indexService().setIsolation( Isolation.ASYNC_OTHER_TX ); itr = indexService().getNodes( key, value1 ).iterator(); assertTrue( !itr.hasNext() ); indexService().index( node1, key, value1 ); itr = indexService().getNodes( key, "tokenize" ).iterator(); assertTrue( !itr.hasNext() ); try { Thread.sleep( 1000 ); } catch ( InterruptedException e ) { Thread.interrupted(); } itr = indexService().getNodes( key, "tokenize" ).iterator(); assertTrue( itr.hasNext() ); indexService().setIsolation( Isolation.SYNC_OTHER_TX ); indexService().removeIndex( node1, key, value1 ); itr = indexService().getNodes( key, value1 ).iterator(); assertTrue( !itr.hasNext() ); node1.delete(); node2.delete(); } public void testSpecific() throws Exception { Node andy = graphDb().createNode(); Node larry = graphDb().createNode(); String key = "atest"; indexService().index( andy, key, "Andy Wachowski" ); indexService().index( larry, key, "Larry Wachowski" ); assertCollection( asCollection( indexService().getNodes( key, "andy wachowski" ) ), andy ); assertCollection( asCollection( indexService().getNodes( key, "Andy Wachowski\t " ) ), andy ); assertCollection( asCollection( indexService().getNodes( key, "wachowski larry" ) ), larry ); assertCollection( asCollection( indexService().getNodes( key, "andy" ) ), andy ); assertCollection( asCollection( indexService().getNodes( key, "Andy" ) ), andy ); assertCollection( asCollection( indexService().getNodes( key, "larry" ) ), larry ); assertCollection( asCollection( indexService().getNodes( key, "andy larry" ) ) ); assertCollection( asCollection( indexService().getNodes( key, "wachowski" ) ), andy, larry ); assertCollection( asCollection( indexService().getNodes( key, "wachow*" ) ) ); andy.delete(); larry.delete(); } public void testAnotherChangeValueBug() throws Exception { Node andy = graphDb().createNode(); Node larry = graphDb().createNode(); andy.setProperty( "name", "Andy Wachowski" ); // Deliberately set Larry's name wrong larry.setProperty( "name", "Andy Wachowski" ); indexService().index( andy, "name", andy.getProperty( "name" ) ); indexService().index( larry, "name", larry.getProperty( "name" ) ); assertCollection( asCollection( indexService().getNodes( "name", "wachowski" ) ), andy, larry ); // Correct Larry's name indexService().removeIndex( larry, "name", larry.getProperty( "name" ) ); larry.setProperty( "name", "Larry Wachowski" ); indexService().index( larry, "name", larry.getProperty( "name" ) ); assertCollection( asCollection( indexService().getNodes( "name", "wachowski" ) ), andy, larry ); } public void testBreakLazyIteratorAfterRemove() throws Exception { int oldLazyThreshold = ( ( LuceneIndexService ) indexService() ).getLazySearchResultThreshold(); int lazyThreshold = 5; ( ( LuceneIndexService ) indexService() ).setLazySearchResultThreshold( lazyThreshold ); List<Node> nodes = new ArrayList<Node>(); String key = "lazykey"; String value = "value"; for ( int i = 0; i < lazyThreshold + 1; i++ ) { Node node = graphDb().createNode(); nodes.add( node ); indexService().index( node, key, value ); } restartTx(); // Assert they're all there IndexHits<Node> hits = indexService().getNodes( key, value ); assertCollection( asCollection( hits ), nodes.toArray( new Node[ 0 ] ) ); assertEquals( nodes.size(), hits.size() ); // Search again, but don't iterate the result. then remove one node // and see how it goes (w/o committing). hits = indexService().getNodes( key, value ); Node anyNode = nodes.get( nodes.size() - 1 ); indexService().removeIndex( anyNode, key, value ); assertCollection( asCollection( hits ), nodes.toArray( new Node[ 0 ] ) ); assertEquals( nodes.size(), hits.size() ); restartTx( false ); // do it again, but this time commit the removal hits = indexService().getNodes( key, value ); indexService().removeIndex( anyNode, key, value ); Node anyOtherNode = nodes.get( nodes.size() - 2 ); anyOtherNode.delete(); restartTx(); // We don't know exactly how lucene does here... if the removedIndex // will cause any trouble (if it has been cached in lucene). // So just see if we get any exceptions. for ( Node hit : hits ) { } ( ( LuceneIndexService ) indexService() ).setLazySearchResultThreshold( oldLazyThreshold ); } }