You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by mr...@apache.org on 2016/06/23 22:26:09 UTC

[04/11] usergrid git commit: Implement smarter loading of unique value entries in hopes to avoid duplicate problems. Update UniqueValueScanner tool to allow specific entity fetch.

Implement smarter loading of unique value entries in hopes to avoid duplicate problems.  Update UniqueValueScanner tool to allow specific entity fetch.


Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/75d2254e
Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/75d2254e
Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/75d2254e

Branch: refs/heads/release-2.1.1
Commit: 75d2254e3f57bdf78a965e71255910e25121fe94
Parents: 1997b57
Author: Michael Russo <mr...@apigee.com>
Authored: Wed Jun 22 16:34:28 2016 -0700
Committer: Michael Russo <mr...@apigee.com>
Committed: Wed Jun 22 16:34:28 2016 -0700

----------------------------------------------------------------------
 .../mvcc/stage/write/WriteUniqueVerify.java     |  34 +++++-
 .../UniqueValueSerializationStrategy.java       |   3 +-
 .../UniqueValueSerializationStrategyImpl.java   |  86 ++++++++++++----
 .../collection/EntityCollectionManagerIT.java   |   4 +-
 ...niqueValueSerializationStrategyImplTest.java | 103 ++++++++++++++++++-
 .../collection/devices/DevicesResourceIT.java   |   3 +-
 .../usergrid/tools/UniqueValueScanner.java      |  47 +++++++--
 7 files changed, 245 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
index afe681e..7b76dc8 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
@@ -18,10 +18,7 @@
 package org.apache.usergrid.persistence.collection.mvcc.stage.write;
 
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import com.netflix.hystrix.HystrixCommandProperties;
 import org.slf4j.Logger;
@@ -112,6 +109,7 @@ public class WriteUniqueVerify implements Action1<CollectionIoEvent<MvccEntity>>
         // Construct all the functions for verifying we're unique
         //
 
+        final Map<String, Field> preWriteUniquenessViolations = new HashMap<>( uniqueFields.size() );
 
         for ( final Field field : EntityUtils.getUniqueFields(entity)) {
 
@@ -121,6 +119,28 @@ public class WriteUniqueVerify implements Action1<CollectionIoEvent<MvccEntity>>
             // use write-first then read strategy
             final UniqueValue written = new UniqueValueImpl( field, mvccEntity.getId(), mvccEntity.getVersion() );
 
+            try {
+
+                // loading will retrieve the oldest unique value entry for the field
+                UniqueValueSet set = uniqueValueStrat.load(scope, written.getEntityId().getType(), Collections.singletonList(written.getField()));
+
+
+                set.forEach(uniqueValue -> {
+
+                    if(!uniqueValue.getEntityId().getUuid().equals(written.getEntityId().getUuid())){
+
+                        preWriteUniquenessViolations.put(field.getName(), field);
+
+                    }
+
+                });
+
+
+            } catch (ConnectionException e) {
+
+                throw new RuntimeException("Error connecting to cassandra", e);
+            }
+
             // use TTL in case something goes wrong before entity is finally committed
             final MutationBatch mb = uniqueValueStrat.write( scope, written, serializationFig.getTimeout() );
 
@@ -128,6 +148,11 @@ public class WriteUniqueVerify implements Action1<CollectionIoEvent<MvccEntity>>
             uniqueFields.add(field);
         }
 
+        if(preWriteUniquenessViolations.size() > 0 ){
+            throw new WriteUniqueVerifyException(mvccEntity, scope,
+                preWriteUniquenessViolations );
+        }
+
         //short circuit nothing to do
         if ( uniqueFields.size() == 0 ) {
             return  ;
@@ -191,6 +216,7 @@ public class WriteUniqueVerify implements Action1<CollectionIoEvent<MvccEntity>>
             //now get the set of fields back
             final UniqueValueSet uniqueValues;
             try {
+                // load ascending for verification to make sure we wrote is the last read back
                 uniqueValues = uniqueValueSerializationStrategy.load( scope, consistencyLevel, type,  uniqueFields );
             }
             catch ( ConnectionException e ) {

http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
index 3645107..95cfa68 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
@@ -59,7 +59,8 @@ public interface UniqueValueSerializationStrategy extends Migration, VersionedDa
     MutationBatch write( ApplicationScope applicationScope, UniqueValue uniqueValue, int timeToLive );
 
     /**
-     * Load UniqueValue that matches field from collection or null if that value does not exist.
+     * Load UniqueValue that matches field from collection or null if that value does not exist.  Returns the oldest
+     * unique value entry if more than 1 exists
      *
      * @param applicationScope scope in which to look for field name/value
      * @param type The type the unique value exists within

http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
index f7d5199..a323746 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
@@ -18,13 +18,9 @@
 package org.apache.usergrid.persistence.collection.serialization.impl;
 
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
 
+import com.netflix.astyanax.util.RangeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,7 +51,6 @@ import com.netflix.astyanax.model.Column;
 import com.netflix.astyanax.model.ConsistencyLevel;
 import com.netflix.astyanax.model.Row;
 import com.netflix.astyanax.query.RowQuery;
-import com.netflix.astyanax.util.RangeBuilder;
 
 
 /**
@@ -271,7 +266,8 @@ public abstract class UniqueValueSerializationStrategyImpl<FieldKey, EntityKey>
 
         Iterator<Row<ScopedRowKey<FieldKey>, EntityVersion>> results =
             keyspace.prepareQuery( CF_UNIQUE_VALUES ).setConsistencyLevel( consistencyLevel ).getKeySlice( keys )
-                    .withColumnRange( new RangeBuilder().setLimit( 1 ).build() ).execute().getResult().iterator();
+                .withColumnRange(new RangeBuilder().setLimit(serializationFig.getBufferSize()).build())
+                .execute().getResult().iterator();
 
 
         while ( results.hasNext() )
@@ -280,7 +276,6 @@ public abstract class UniqueValueSerializationStrategyImpl<FieldKey, EntityKey>
 
             final Row<ScopedRowKey<FieldKey>, EntityVersion> unique = results.next();
 
-
             final Field field = parseRowKey( unique.getKey() );
 
             final Iterator<Column<EntityVersion>> columnList = unique.getColumns().iterator();
@@ -290,20 +285,75 @@ public abstract class UniqueValueSerializationStrategyImpl<FieldKey, EntityKey>
                 continue;
             }
 
-            final EntityVersion entityVersion = columnList.next().getName();
+            // these used duplicate tracking and cleanup
+            UUID oldestEntityUUID = null;
+            UniqueValueImpl firstUniqueValue = null;
+
+
+            /**
+             *  While iterating the columns, a rule is being enforced to only EVER return the oldest UUID.  This means
+             *  the UUID with the oldest timestamp ( it was the original entity written for the unique value ).
+             *
+             *  We do this to prevent cycling of unique value -> entity UUID mappings as this data is ordered by the
+             *  entity's version and not the entity's timestamp itself.
+             *
+             *  If newer entity UUIDs are encountered, they are removed from the unique value tables, however their
+             *  backing serialized entity data is left in tact in case a cleanup / audit is later needed.
+             */
+            while (columnList.hasNext()) {
+
+                final EntityVersion entityVersion = columnList.next().getName();
+
+                final UUID currentEntityUUID = entityVersion.getEntityId().getUuid();
+                final UniqueValueImpl uniqueValue =
+                    new UniqueValueImpl(field, entityVersion.getEntityId(), entityVersion.getEntityVersion());
+
+
+                // keep track of the first and oldest entity (not version),
+                // knowing the the first one may not be the 'oldest'
+                if(oldestEntityUUID == null){
+
+                    oldestEntityUUID = currentEntityUUID;
+                    firstUniqueValue = uniqueValue;
+
+                }else if(currentEntityUUID.timestamp() < oldestEntityUUID.timestamp()){
 
+                    oldestEntityUUID = currentEntityUUID;
+                }
 
-            final UniqueValueImpl uniqueValue =
-                new UniqueValueImpl( field, entityVersion.getEntityId(), entityVersion.getEntityVersion() );
 
-            if(logger.isTraceEnabled()){
-                logger.trace("Putting unique value [{}={}] into result set with entity id [{}] and entity version [{}]",
-                    field.getName(), field.getValue().toString(),
-                    entityVersion.getEntityId(),
-                    entityVersion.getEntityVersion());
+                // only return the oldest (original) unique value entries
+                if(currentEntityUUID.timestamp() <= oldestEntityUUID.timestamp() ){
+
+                    if (logger.isTraceEnabled()) {
+                    logger.trace("Putting unique value [{}={}] into result set with entity id [{}] and entity version [{}]",
+                        field.getName(), field.getValue().toString(),
+                        entityVersion.getEntityId(),
+                        entityVersion.getEntityVersion());
+                     }
+
+                    uniqueValueSet.addValue(uniqueValue);
+
+                }
+                // remove the newer duplicated unique value entries
+                else{
+
+                    delete(appScope, uniqueValue ).execute();
+
+                }
+
             }
 
-            uniqueValueSet.addValue( uniqueValue );
+            // check to see if the very first unique value entry was overwritten because it was not the oldest
+            // if so, clean up its unique index
+            if( !uniqueValueSet.getValue( firstUniqueValue.getField().getName() )
+                .getEntityId().getUuid().equals(firstUniqueValue.getEntityId().getUuid()) ){
+
+                delete(appScope, firstUniqueValue).execute();
+
+            }
+
+
         }
 
         return uniqueValueSet;

http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/EntityCollectionManagerIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/EntityCollectionManagerIT.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/EntityCollectionManagerIT.java
index 10c7eb7..f828c65 100644
--- a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/EntityCollectionManagerIT.java
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/EntityCollectionManagerIT.java
@@ -758,7 +758,7 @@ public class EntityCollectionManagerIT {
         assertNotNull( "Version was assigned", createReturned.getVersion() );
 
         FieldSet fieldResults =
-            manager.getEntitiesFromFields( newEntity.getId().getType(), Arrays.<Field>asList( expectedInteger ), false)
+            manager.getEntitiesFromFields( newEntity.getId().getType(), Arrays.<Field>asList( expectedInteger ), true)
                    .toBlocking().last();
 
         assertEquals( 1, fieldResults.size() );
@@ -775,7 +775,7 @@ public class EntityCollectionManagerIT {
 
         //try to load via the unique field, should have triggered repair
         final FieldSet results =
-            manager.getEntitiesFromFields( newEntity.getId().getType(), Arrays.<Field>asList( expectedInteger ), false)
+            manager.getEntitiesFromFields( newEntity.getId().getType(), Arrays.<Field>asList( expectedInteger ), true)
                    .toBlocking().last();
 
 

http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
index fcf22cf..6c4e72b 100644
--- a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
@@ -33,7 +33,6 @@ import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
 import org.apache.usergrid.persistence.collection.serialization.UniqueValue;
 import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
 import org.apache.usergrid.persistence.collection.serialization.UniqueValueSet;
-import org.apache.usergrid.persistence.collection.serialization.impl.UniqueValueImpl;
 import org.apache.usergrid.persistence.core.guice.MigrationManagerRule;
 import org.apache.usergrid.persistence.core.scope.ApplicationScope;
 import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl;
@@ -341,4 +340,106 @@ public abstract class UniqueValueSerializationStrategyImplTest {
 
     }
 
+    /**
+     * Test that inserting duplicates always show the oldest entity UUID being returned (versions of that OK to change).
+     *
+     * @throws ConnectionException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testWritingDuplicates() throws ConnectionException, InterruptedException {
+
+        ApplicationScope scope =
+            new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+        IntegerField field = new IntegerField( "count", 5 );
+        Id entityId1 = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+        Id entityId2 = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+
+
+
+        UUID version1 = UUIDGenerator.newTimeUUID();
+        UUID version2 = UUIDGenerator.newTimeUUID();
+
+        UniqueValue stored1 = new UniqueValueImpl( field, entityId1, version2 );
+        UniqueValue stored2 = new UniqueValueImpl( field, entityId2,  version1 );
+
+
+        strategy.write( scope, stored1 ).execute();
+        strategy.write( scope, stored2 ).execute();
+
+        // load descending to get the older version of entity for this unique value
+        UniqueValueSet fields = strategy.load( scope, entityId1.getType(), Collections.<Field>singleton( field ));
+
+        UniqueValue retrieved = fields.getValue( field.getName() );
+
+        // validate that the first entity UUID is returned after inserting a duplicate mapping
+        assertEquals( stored1, retrieved );
+
+
+
+        UUID version3 = UUIDGenerator.newTimeUUID();
+        UniqueValue stored3 = new UniqueValueImpl( field, entityId2, version3);
+        strategy.write( scope, stored3 ).execute();
+
+        // load the values again, we should still only get back the original unique value
+        fields = strategy.load( scope, entityId1.getType(), Collections.<Field>singleton( field ));
+
+        retrieved = fields.getValue( field.getName() );
+
+        // validate that the first entity UUID is still returned after inserting duplicate with newer version
+        assertEquals( stored1, retrieved );
+
+
+        UUID version4 = UUIDGenerator.newTimeUUID();
+        UniqueValue stored4 = new UniqueValueImpl( field, entityId1, version4);
+        strategy.write( scope, stored4 ).execute();
+
+        // load the values again, now we should get the latest version of the original UUID written
+        fields = strategy.load( scope, entityId1.getType(), Collections.<Field>singleton( field ));
+
+        retrieved = fields.getValue( field.getName() );
+
+        // validate that the first entity UUID is still returned, but with the latest version
+        assertEquals( stored4, retrieved );
+
+    }
+
+    /**
+     * Test that inserting multiple versions of the same entity UUID result in the latest version being returned.
+     *
+     * @throws ConnectionException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testMultipleVersionsSameEntity() throws ConnectionException, InterruptedException {
+
+        ApplicationScope scope =
+            new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+        IntegerField field = new IntegerField( "count", 5 );
+        Id entityId1 = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+
+
+
+        UUID version1 = UUIDGenerator.newTimeUUID();
+        UUID version2 = UUIDGenerator.newTimeUUID();
+
+        UniqueValue stored1 = new UniqueValueImpl( field, entityId1, version1 );
+        UniqueValue stored2 = new UniqueValueImpl( field, entityId1,  version2 );
+
+
+        strategy.write( scope, stored1 ).execute();
+        strategy.write( scope, stored2 ).execute();
+
+        // load descending to get the older version of entity for this unique value
+        UniqueValueSet fields = strategy.load( scope, entityId1.getType(), Collections.<Field>singleton( field ));
+
+        UniqueValue retrieved = fields.getValue( field.getName() );
+        Assert.assertNotNull( retrieved );
+        assertEquals( stored2, retrieved );
+
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/devices/DevicesResourceIT.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/devices/DevicesResourceIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/devices/DevicesResourceIT.java
index 02716a7..67cf19f 100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/devices/DevicesResourceIT.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/devices/DevicesResourceIT.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.UUID;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
 import org.apache.usergrid.rest.test.resource.AbstractRestIT;
 import org.apache.usergrid.rest.test.resource.endpoints.CollectionEndpoint;
 import org.apache.usergrid.rest.test.resource.model.ApiResponse;
@@ -45,7 +46,7 @@ public class DevicesResourceIT extends AbstractRestIT {
     public void putWithUUIDShouldCreateAfterDelete() throws IOException {
 
         Entity payload = new Entity().chainPut("name", "foo");
-        UUID uuid = UUID.randomUUID();
+        UUID uuid = UUIDGenerator.newTimeUUID();
 
 
         CollectionEndpoint devicesResource  =this.app().collection("devices");

http://git-wip-us.apache.org/repos/asf/usergrid/blob/75d2254e/stack/tools/src/main/java/org/apache/usergrid/tools/UniqueValueScanner.java
----------------------------------------------------------------------
diff --git a/stack/tools/src/main/java/org/apache/usergrid/tools/UniqueValueScanner.java b/stack/tools/src/main/java/org/apache/usergrid/tools/UniqueValueScanner.java
index f884a1d..bdebd01 100644
--- a/stack/tools/src/main/java/org/apache/usergrid/tools/UniqueValueScanner.java
+++ b/stack/tools/src/main/java/org/apache/usergrid/tools/UniqueValueScanner.java
@@ -21,13 +21,11 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.UUID;
 
-import com.google.common.base.Optional;
 import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
 import com.netflix.astyanax.model.Column;
 import com.netflix.astyanax.util.RangeBuilder;
 import org.apache.usergrid.persistence.Entity;
 import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.persistence.collection.MvccEntity;
 import org.apache.usergrid.persistence.collection.serialization.MvccEntitySerializationStrategy;
 import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
 import org.apache.usergrid.persistence.collection.serialization.UniqueValueSet;
@@ -60,6 +58,9 @@ public class UniqueValueScanner extends ToolBase {
 
     private static final String ENTITY_NAME_ARG = "entityName";
 
+    private static final String ENTITY_FIELD_TYPE_ARG = "fieldType";
+
+
 
     //copied shamelessly from unique value serialization strat.
     private static final ScopedRowKeySerializer<TypeField> ROW_KEY_SER =
@@ -100,11 +101,16 @@ public class UniqueValueScanner extends ToolBase {
         options.addOption( collectionOption );
 
         Option specificEntityNameOption =
-            OptionBuilder.withArgName(ENTITY_NAME_ARG).hasArg().isRequired( true ).withDescription( "specific entity name" )
+            OptionBuilder.withArgName(ENTITY_NAME_ARG).hasArg().isRequired( false ).withDescription( "specific entity name" )
                 .create(ENTITY_NAME_ARG);
 
         options.addOption( specificEntityNameOption );
 
+        Option fieldTypeOption =
+            OptionBuilder.withArgName(ENTITY_FIELD_TYPE_ARG).hasArg().isRequired( false ).withDescription( "field type" )
+                .create(ENTITY_FIELD_TYPE_ARG);
+
+        options.addOption( fieldTypeOption );
 
         return options;
     }
@@ -126,14 +132,15 @@ public class UniqueValueScanner extends ToolBase {
             appToFilter = UUID.fromString(line.getOptionValue(APPLICATION_ARG));
         }
 
+        logger.info("Staring Tool: UniqueValueScanner");
 
-        logger.info("Starting entity unique scanner");
 
         keyspace = injector.getInstance(com.netflix.astyanax.Keyspace.class);
         mvccEntitySerializationStrategy = injector.getInstance(MvccEntitySerializationStrategy.class);
         uniqueValueSerializationStrategy = injector.getInstance(UniqueValueSerializationStrategy.class);
 
-
+        String fieldType =
+            line.getOptionValue(ENTITY_FIELD_TYPE_ARG) != null ?  line.getOptionValue(ENTITY_FIELD_TYPE_ARG)  : "name" ;
         String entityType = line.getOptionValue(ENTITY_TYPE_ARG);
         String entityName = line.getOptionValue(ENTITY_NAME_ARG);
 
@@ -149,16 +156,40 @@ public class UniqueValueScanner extends ToolBase {
                     "collection name).");
             }
 
+            logger.info("Running entity unique load only");
+
+
             //do stuff
             UniqueValueSet uniqueValueSet = uniqueValueSerializationStrategy.load(
                 new ApplicationScopeImpl( new SimpleId(appToFilter, "application" ) ),
                 entityType,
-                Collections.singletonList(new StringField( "name", entityName) ));
+                Collections.singletonList(new StringField( fieldType, entityName) ));
+
+            StringBuilder stringBuilder = new StringBuilder();
+
+            stringBuilder.append("[");
 
-            logger.info("Returned unique value set from serialization load = {}", uniqueValueSet);
+            uniqueValueSet.forEach( uniqueValue -> {
+
+
+                String entry = "fieldName="+uniqueValue.getField().getName()+
+                    ", fieldValue="+uniqueValue.getField().getValue()+
+                    ", uuid="+uniqueValue.getEntityId().getUuid()+
+                    ", type="+uniqueValue.getEntityId().getType()+
+                    ", version="+uniqueValue.getEntityVersion();
+                stringBuilder.append("{").append(entry).append("},");
+            });
+
+            stringBuilder.deleteCharAt(stringBuilder.length() -1);
+            stringBuilder.append("]");
+
+            logger.info("Returned unique value set from serialization load = {}", stringBuilder.toString());
 
         } else {
 
+            logger.info("Running entity unique scanner only");
+
+
             // scan through all unique values and log some info
 
             Iterator<com.netflix.astyanax.model.Row<ScopedRowKey<TypeField>, EntityVersion>> rows = null;
@@ -181,7 +212,7 @@ public class UniqueValueScanner extends ToolBase {
                 String scopeType = row.getKey().getScope().getType();
                 UUID scopeUUID = row.getKey().getScope().getUuid();
 
-                if (!fieldName.equalsIgnoreCase("name") ||
+                if (!fieldName.equalsIgnoreCase(fieldType) ||
                     (finalAppToFilter != null && !finalAppToFilter.equals(scopeUUID))
                     ) {
                     // do nothing