Initial support for select mappings with entity object fields (i.e. nested fields)
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/596e0fc5 Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/596e0fc5 Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/596e0fc5 Branch: refs/heads/usergrid-1268-akka-211 Commit: 596e0fc5cef2eb1ae4aba40343bf27e73aee86d6 Parents: 7fdca3d Author: Dave Johnson <[email protected]> Authored: Wed May 18 17:24:25 2016 -0400 Committer: Dave Johnson <[email protected]> Committed: Wed May 18 17:24:25 2016 -0400 ---------------------------------------------------------------------- .../read/search/CandidateEntityFilter.java | 59 ++++++++++++++- .../apache/usergrid/persistence/IndexIT.java | 80 ++++++++++++++++++++ 2 files changed, 135 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/596e0fc5/stack/core/src/main/java/org/apache/usergrid/corepersistence/pipeline/read/search/CandidateEntityFilter.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/pipeline/read/search/CandidateEntityFilter.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/pipeline/read/search/CandidateEntityFilter.java index d47e96c..261259b 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/pipeline/read/search/CandidateEntityFilter.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/pipeline/read/search/CandidateEntityFilter.java @@ -27,7 +27,9 @@ import org.apache.usergrid.persistence.index.*; import org.apache.usergrid.persistence.index.impl.IndexProducer; import org.apache.usergrid.persistence.model.field.DistanceField; import org.apache.usergrid.persistence.model.field.DoubleField; +import org.apache.usergrid.persistence.model.field.EntityObjectField; import org.apache.usergrid.persistence.model.field.Field; +import org.apache.usergrid.persistence.model.field.value.EntityObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -123,12 +125,26 @@ public class CandidateEntityFilter extends AbstractFilter<FilterResult<Candidate if (mappings.size() > 0) { Map<String,Field> fieldMap = new HashMap<String, Field>(mappings.size()); rx.Observable.from(mappings) - .filter(mapping -> entity.getFieldMap().containsKey(mapping.getSourceFieldName())) + + .filter(mapping -> { + if ( entity.getFieldMap().containsKey(mapping.getSourceFieldName())) { + return true; + } + String[] parts = mapping.getSourceFieldName().split("\\."); + return nestedFieldCheck( parts, entity.getFieldMap() ); + }) + .doOnNext(mapping -> { Field field = entity.getField(mapping.getSourceFieldName()); - field.setName(mapping.getTargetFieldName()); - fieldMap.put(mapping.getTargetFieldName(),field); - }).toBlocking().last(); + if ( field != null ) { + field.setName( mapping.getTargetFieldName() ); + fieldMap.put( mapping.getTargetFieldName(), field ); + } else { + String[] parts = mapping.getSourceFieldName().split("\\."); + nestedFieldSet( fieldMap, parts, entity.getFieldMap() ); + } + }).toBlocking().lastOrDefault(null); + entity.setFieldMap(fieldMap); } return entityFilterResult; @@ -144,6 +160,41 @@ public class CandidateEntityFilter extends AbstractFilter<FilterResult<Candidate } + private void nestedFieldSet( Map<String, Field> result, String[] parts, Map<String, Field> fieldMap) { + if ( parts.length > 0 ) { + if ( fieldMap.containsKey( parts[0] )) { + Field field = fieldMap.get( parts[0] ); + if ( field instanceof EntityObjectField ) { + EntityObjectField eof = (EntityObjectField)field; + if ( result.get( parts[0] ) == null ) { + result.put( parts[0], new EntityObjectField( parts[0], new EntityObject() ) ); + } + nestedFieldSet( + ((EntityObjectField)result.get( parts[0] )).getValue().getFieldMap(), + Arrays.copyOfRange(parts, 1, parts.length), + eof.getValue().getFieldMap()); + } else { + result.put( parts[0], field ); + } + } + } + } + + + private boolean nestedFieldCheck( String[] parts, Map<String, Field> fieldMap) { + if ( parts.length > 0 ) { + if ( fieldMap.containsKey( parts[0] )) { + Field field = fieldMap.get( parts[0] ); + if ( field instanceof EntityObjectField ) { + EntityObjectField eof = (EntityObjectField)field; + return nestedFieldCheck( Arrays.copyOfRange(parts, 1, parts.length), eof.getValue().getFieldMap()); + } else { + return true; + } + } + } + return false; + } /** http://git-wip-us.apache.org/repos/asf/usergrid/blob/596e0fc5/stack/core/src/test/java/org/apache/usergrid/persistence/IndexIT.java ---------------------------------------------------------------------- diff --git a/stack/core/src/test/java/org/apache/usergrid/persistence/IndexIT.java b/stack/core/src/test/java/org/apache/usergrid/persistence/IndexIT.java index f4aa204..7e38f17 100644 --- a/stack/core/src/test/java/org/apache/usergrid/persistence/IndexIT.java +++ b/stack/core/src/test/java/org/apache/usergrid/persistence/IndexIT.java @@ -17,6 +17,7 @@ package org.apache.usergrid.persistence; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.UUID; @@ -461,4 +462,83 @@ public class IndexIT extends AbstractCoreIT { } + + @Test + public void testSelectMappings() throws Exception { + + UUID applicationId = app.getId(); + + EntityManager em = setup.getEmf().getEntityManager(applicationId); + + Map<String, Object> entity1 = new HashMap<String, Object>() {{ + put("name","name_1"); + put("status", "pickled"); + put("data", new HashMap() {{ + put("xfactor", 5.1); + put("rando", "bar"); + }}); + }}; + em.create("names", entity1); + + Map<String, Object> entity2 = new HashMap<String, Object>() {{ + put("name","name_2"); + put("status", "pickled"); + put("data", new HashMap() {{ + put("xfactor", 5.1); + put("rando", "bar"); + }}); + }}; + em.create("names", entity2); + + app.refreshIndex(); + + { + Query query = Query.fromQL("select status where status = 'pickled'"); + Results r = em.searchCollection( em.getApplicationRef(), "names", query ); + assertTrue(r.getEntities() != null && r.getEntities().size() == 2); + Entity first = r.getEntities().get(0); + assertTrue(first.getDynamicProperties().size() == 2); + } + + { + Query query = Query.fromQL( "select status, data.rando where data.rando = 'bar'" ); + Results r = em.searchCollection( em.getApplicationRef(), "names", query ); + assertTrue( r.getEntities() != null && r.getEntities().size() == 2 ); + + Entity first = r.getEntities().get( 0 ); + + assertNotNull( first.getProperty("status") ); + assertEquals( first.getProperty("status"), "pickled" ); + + assertNotNull( first.getProperty("data") ); + assertEquals( ((Map<String, Object>)first.getProperty("data")).get("rando"), "bar" ); + + assertTrue( first.getDynamicProperties().size() == 3 ); + } + + { + // query for only one bogus field name should return empty entities + Query query = Query.fromQL( "select data.rando where status = 'pickled'" ); + Results r = em.searchCollection( em.getApplicationRef(), "names", query ); + assertTrue( r.getEntities() != null && r.getEntities().size() == 2 ); + + Entity first = r.getEntities().get( 0 ); + + assertNotNull( first.getProperty("data") ); + assertEquals( ((Map<String, Object>)first.getProperty("data")).get("rando"), "bar" ); + + assertTrue( first.getDynamicProperties().size() == 2 ); + } + + { + // query for only one bogus field name should return empty entities + Query query = Query.fromQL( "select data.bogusfieldname where status = 'pickled'" ); + Results r = em.searchCollection( em.getApplicationRef(), "names", query ); + assertTrue( r.getEntities() != null && r.getEntities().size() == 2 ); + Entity first = r.getEntities().get( 0 ); + assertTrue( first.getDynamicProperties().size() == 1 ); + } + + } + }
