| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. The ASF licenses this file to You |
| * under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. For additional information regarding |
| * copyright in this work, please see the NOTICE file in the top level |
| * directory of this distribution. |
| */ |
| package org.apache.usergrid.persistence.index.impl; |
| |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import org.apache.usergrid.persistence.collection.util.EntityUtils; |
| import org.apache.usergrid.persistence.core.scope.ApplicationScope; |
| import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl; |
| import org.apache.usergrid.persistence.core.test.UseModules; |
| import org.apache.usergrid.persistence.index.EntityIndex; |
| import org.apache.usergrid.persistence.index.EntityIndexBatch; |
| import org.apache.usergrid.persistence.index.EntityIndexFactory; |
| import org.apache.usergrid.persistence.index.IndexScope; |
| import org.apache.usergrid.persistence.index.SearchTypes; |
| import org.apache.usergrid.persistence.index.exceptions.QueryParseException; |
| import org.apache.usergrid.persistence.index.guice.TestIndexModule; |
| import org.apache.usergrid.persistence.index.query.CandidateResult; |
| import org.apache.usergrid.persistence.index.query.CandidateResults; |
| import org.apache.usergrid.persistence.index.query.Query; |
| import org.apache.usergrid.persistence.model.entity.Entity; |
| import org.apache.usergrid.persistence.model.entity.Id; |
| import org.apache.usergrid.persistence.model.entity.SimpleId; |
| import org.apache.usergrid.persistence.model.util.UUIDGenerator; |
| |
| import com.google.inject.Inject; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.fail; |
| |
| |
| @RunWith( EsRunner.class ) |
| @UseModules( { TestIndexModule.class } ) |
| public class EntityConnectionIndexImplTest extends BaseIT { |
| |
| private static final Logger log = LoggerFactory.getLogger( EntityConnectionIndexImplTest.class ); |
| |
| // @ClassRule |
| // public static ElasticSearchResource es = new ElasticSearchResource(); |
| |
| |
| @Inject |
| public EntityIndexFactory ecif; |
| |
| |
| @Test |
| public void testBasicOperation() throws IOException, InterruptedException { |
| |
| Id appId = new SimpleId( "application" ); |
| ApplicationScope applicationScope = new ApplicationScopeImpl( appId ); |
| |
| // create a muffin |
| Entity muffin = new Entity( new SimpleId( UUIDGenerator.newTimeUUID(), "muffin" ) ); |
| |
| muffin = EntityIndexMapUtils.fromMap( muffin, new HashMap<String, Object>() {{ |
| put( "size", "Large" ); |
| put( "flavor", "Blueberry" ); |
| put( "stars", 5 ); |
| }} ); |
| EntityUtils.setVersion( muffin, UUIDGenerator.newTimeUUID() ); |
| |
| Entity egg = new Entity( new SimpleId( UUIDGenerator.newTimeUUID(), "egg" ) ); |
| |
| egg = EntityIndexMapUtils.fromMap( egg, new HashMap<String, Object>() {{ |
| put( "size", "Large" ); |
| put( "type", "scramble" ); |
| put( "stars", 5 ); |
| }} ); |
| EntityUtils.setVersion( egg, UUIDGenerator.newTimeUUID() ); |
| |
| Entity oj = new Entity( new SimpleId( UUIDGenerator.newTimeUUID(), "juice" ) ); |
| |
| oj = EntityIndexMapUtils.fromMap( oj, new HashMap<String, Object>() {{ |
| put( "size", "Large" ); |
| put( "type", "pulpy" ); |
| put( "stars", 3 ); |
| }} ); |
| EntityUtils.setVersion( oj, UUIDGenerator.newTimeUUID() ); |
| |
| |
| // create a person who likes muffins |
| Id personId = new SimpleId( UUIDGenerator.newTimeUUID(), "person" ); |
| |
| |
| assertNotNull( personId ); |
| assertNotNull( personId.getType() ); |
| assertNotNull( personId.getUuid() ); |
| |
| // index connection of "person Dave likes Large Blueberry muffin" |
| |
| IndexScope searchScope = new IndexScopeImpl( personId, "likes" ); |
| |
| //create another scope we index in, want to be sure these scopes are filtered |
| IndexScope otherIndexScope = |
| new IndexScopeImpl( new SimpleId( UUIDGenerator.newTimeUUID(), "animal" ), "likes" ); |
| |
| EntityIndex personLikesIndex = ecif.createEntityIndex( applicationScope ); |
| |
| EntityIndexBatch batch = personLikesIndex.createBatch(); |
| |
| //add to both scopes |
| |
| //add a muffin |
| batch.index( searchScope, muffin ); |
| batch.index( otherIndexScope, muffin ); |
| |
| //add the eggs |
| batch.index( searchScope, egg ); |
| batch.index( otherIndexScope, egg ); |
| |
| //add the oj |
| batch.index( searchScope, oj ); |
| batch.index( otherIndexScope, oj ); |
| |
| batch.executeAndRefresh(); |
| personLikesIndex.refresh(); |
| |
| |
| EsTestUtils.waitForTasks(personLikesIndex); |
| Thread.sleep( 1000 ); |
| |
| // now, let's search for muffins |
| CandidateResults likes = personLikesIndex |
| .search( searchScope, SearchTypes.fromTypes( muffin.getId().getType() ), Query.fromQL( "select *" ) ); |
| assertEquals( 1, likes.size() ); |
| assertEquals( muffin.getId(), likes.get( 0 ).getId() ); |
| |
| // now, let's search for egg |
| likes = personLikesIndex |
| .search( searchScope, SearchTypes.fromTypes( egg.getId().getType() ), Query.fromQL( "select *" ) ); |
| assertEquals( 1, likes.size() ); |
| assertEquals( egg.getId(), likes.get( 0 ).getId() ); |
| |
| // search for OJ |
| likes = personLikesIndex |
| .search( searchScope, SearchTypes.fromTypes( oj.getId().getType() ), Query.fromQL( "select *" ) ); |
| assertEquals( 1, likes.size() ); |
| assertEquals( oj.getId(), likes.get( 0 ).getId() ); |
| |
| |
| //now lets search for all explicitly |
| likes = personLikesIndex.search( searchScope, |
| SearchTypes.fromTypes( muffin.getId().getType(), egg.getId().getType(), oj.getId().getType() ), |
| Query.fromQL( "select *" ) ); |
| assertEquals( 3, likes.size() ); |
| assertContains( egg.getId(), likes ); |
| assertContains( muffin.getId(), likes ); |
| assertContains( oj.getId(), likes ); |
| |
| //now lets search for all explicitly |
| likes = personLikesIndex.search( searchScope, SearchTypes.allTypes(), Query.fromQL( "select *" ) ); |
| assertEquals( 3, likes.size() ); |
| assertContains( egg.getId(), likes ); |
| assertContains( muffin.getId(), likes ); |
| assertContains( oj.getId(), likes ); |
| |
| |
| //now search all entity types with a query that returns a subset |
| likes = personLikesIndex.search( searchScope, |
| SearchTypes.fromTypes( muffin.getId().getType(), egg.getId().getType(), oj.getId().getType() ), |
| Query.fromQL( "select * where stars = 5" ) ); |
| assertEquals( 2, likes.size() ); |
| assertContains( egg.getId(), likes ); |
| assertContains( muffin.getId(), likes ); |
| |
| |
| //now search with no types, we should get only the results that match |
| likes = personLikesIndex |
| .search( searchScope, SearchTypes.allTypes(), Query.fromQL( "select * where stars = 5" ) ); |
| assertEquals( 2, likes.size() ); |
| assertContains( egg.getId(), likes ); |
| assertContains( muffin.getId(), likes ); |
| } |
| |
| |
| @Test |
| public void testDelete() throws IOException, InterruptedException { |
| |
| Id appId = new SimpleId( "application" ); |
| ApplicationScope applicationScope = new ApplicationScopeImpl( appId ); |
| |
| // create a muffin |
| Entity muffin = new Entity( new SimpleId( UUIDGenerator.newTimeUUID(), "muffin" ) ); |
| |
| muffin = EntityIndexMapUtils.fromMap( muffin, new HashMap<String, Object>() {{ |
| put( "size", "Large" ); |
| put( "flavor", "Blueberry" ); |
| put( "stars", 5 ); |
| }} ); |
| EntityUtils.setVersion( muffin, UUIDGenerator.newTimeUUID() ); |
| |
| Entity egg = new Entity( new SimpleId( UUIDGenerator.newTimeUUID(), "egg" ) ); |
| |
| egg = EntityIndexMapUtils.fromMap( egg, new HashMap<String, Object>() {{ |
| put( "size", "Large" ); |
| put( "type", "scramble" ); |
| put( "stars", 5 ); |
| }} ); |
| EntityUtils.setVersion( egg, UUIDGenerator.newTimeUUID() ); |
| |
| Entity oj = new Entity( new SimpleId( UUIDGenerator.newTimeUUID(), "juice" ) ); |
| |
| oj = EntityIndexMapUtils.fromMap( oj, new HashMap<String, Object>() {{ |
| put( "size", "Large" ); |
| put( "type", "pulpy" ); |
| put( "stars", 3 ); |
| }} ); |
| EntityUtils.setVersion( oj, UUIDGenerator.newTimeUUID() ); |
| |
| |
| // create a person who likes muffins |
| Id personId = new SimpleId( UUIDGenerator.newTimeUUID(), "person" ); |
| |
| |
| assertNotNull( personId ); |
| assertNotNull( personId.getType() ); |
| assertNotNull( personId.getUuid() ); |
| |
| // index connection of "person Dave likes Large Blueberry muffin" |
| |
| IndexScope searchScope = new IndexScopeImpl( personId, "likes" ); |
| |
| //create another scope we index in, want to be sure these scopes are filtered |
| IndexScope otherIndexScope = |
| new IndexScopeImpl( new SimpleId( UUIDGenerator.newTimeUUID(), "animal" ), "likes" ); |
| |
| EntityIndex personLikesIndex = ecif.createEntityIndex( applicationScope ); |
| |
| EntityIndexBatch batch = personLikesIndex.createBatch(); |
| |
| //add to both scopes |
| |
| //add a muffin |
| batch.index( searchScope, muffin ); |
| batch.index( otherIndexScope, muffin ); |
| |
| //add the eggs |
| batch.index( searchScope, egg ); |
| batch.index( otherIndexScope, egg ); |
| |
| //add the oj |
| batch.index( searchScope, oj ); |
| batch.index( otherIndexScope, oj ); |
| |
| batch.executeAndRefresh(); |
| personLikesIndex.refresh(); |
| |
| EsTestUtils.waitForTasks( personLikesIndex ); |
| Thread.sleep( 1000 ); |
| |
| // now, let's search for muffins |
| CandidateResults likes = personLikesIndex.search( searchScope, |
| SearchTypes.fromTypes( muffin.getId().getType(), egg.getId().getType(), oj.getId().getType() ), |
| Query.fromQL( "select *" ) ); |
| assertEquals( 3, likes.size() ); |
| assertContains( egg.getId(), likes ); |
| assertContains( muffin.getId(), likes ); |
| assertContains( oj.getId(), likes ); |
| |
| |
| //now delete them |
| batch.deindex( searchScope, egg ); |
| batch.deindex( searchScope, muffin ); |
| batch.deindex( searchScope, oj ); |
| batch.executeAndRefresh(); |
| |
| likes = personLikesIndex.search( searchScope, |
| SearchTypes.fromTypes( muffin.getId().getType(), egg.getId().getType(), oj.getId().getType() ), |
| Query.fromQL( "select *" ) ); |
| assertEquals( 0, likes.size() ); |
| } |
| |
| |
| private void assertContains( final Id id, final CandidateResults results ) { |
| for ( CandidateResult result : results ) { |
| if ( result.getId().equals( id ) ) { |
| return; |
| } |
| } |
| |
| fail( String.format( "Could not find id %s in candidate results", id ) ); |
| } |
| } |