Search in sources :

Example 16 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class LocalDatastoreService method createIndexEntities.

/**
 * Splits a full entity into all index entities seen in a projection.
 *
 * @param entity the entity to split
 * @param postfixProps the properties included in the postfix
 * @return A list of the index entities.
 */
private ImmutableList<EntityProto> createIndexEntities(EntityProto entity, Set<String> postfixProps, EntityProtoComparator entityComparator) {
    SetMultimap<String, PropertyValue> toSplit = MultimapBuilder.hashKeys(postfixProps.size()).hashSetValues(1).build();
    Set<String> seen = Sets.newHashSet();
    boolean splitRequired = false;
    for (Property prop : entity.propertys()) {
        if (postfixProps.contains(prop.getName())) {
            // If we have multiple values for any postfix property, we need to split.
            splitRequired |= !seen.add(prop.getName());
            // Only add the value if it matches the query filters
            if (entityComparator.matches(prop)) {
                toSplit.put(prop.getName(), prop.getValue());
            }
        }
    }
    if (!splitRequired) {
        // No need for splitting!
        return ImmutableList.of(entity);
    }
    EntityProto clone = new EntityProto();
    clone.getMutableKey().copyFrom(entity.getKey());
    clone.getMutableEntityGroup();
    List<EntityProto> results = Lists.newArrayList(clone);
    for (Map.Entry<String, Collection<PropertyValue>> entry : toSplit.asMap().entrySet()) {
        if (entry.getValue().size() == 1) {
            // No need for cloning!
            for (EntityProto result : results) {
                result.addProperty().setName(entry.getKey()).setMeaning(Property.Meaning.INDEX_VALUE).getMutableValue().copyFrom(Iterables.getOnlyElement(entry.getValue()));
            }
            continue;
        }
        List<EntityProto> splitResults = Lists.newArrayListWithCapacity(results.size() * entry.getValue().size());
        for (PropertyValue value : entry.getValue()) {
            for (EntityProto result : results) {
                EntityProto split = result.clone();
                split.addProperty().setName(entry.getKey()).setMeaning(Property.Meaning.INDEX_VALUE).getMutableValue().copyFrom(value);
                splitResults.add(split);
            }
        }
        results = splitResults;
    }
    return ImmutableList.copyOf(results);
}
Also used : PropertyValue(com.google.storage.onestore.v3.OnestoreEntity.PropertyValue) Collection(java.util.Collection) ByteString(com.google.protobuf.ByteString) Property(com.google.storage.onestore.v3.OnestoreEntity.Property) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap) EntityProto(com.google.storage.onestore.v3.OnestoreEntity.EntityProto)

Example 17 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class LocalDatastoreService method getIndices.

// status
@SuppressWarnings("unused")
public CompositeIndices getIndices(Status status, StringProto req) {
    Set<Index> indexSet = LocalCompositeIndexManager.getInstance().getIndexes();
    CompositeIndices answer = new CompositeIndices();
    for (Index index : indexSet) {
        CompositeIndex ci = wrapIndexInCompositeIndex(req.getValue(), index);
        answer.addIndex(ci);
    }
    return answer;
}
Also used : CompositeIndex(com.google.storage.onestore.v3.OnestoreEntity.CompositeIndex) Index(com.google.storage.onestore.v3.OnestoreEntity.Index) CompositeIndex(com.google.storage.onestore.v3.OnestoreEntity.CompositeIndex) CompositeIndices(com.google.apphosting.datastore.DatastoreV3Pb.CompositeIndices)

Example 18 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class LocalCompositeIndexManager method queryIndexList.

/**
 * Get the single composite index used by this query, if any, as a list.
 */
public List<Index> queryIndexList(DatastoreV3Pb.Query query) {
    IndexComponentsOnlyQuery indexOnlyQuery = new IndexComponentsOnlyQuery(query);
    Index index = compositeIndexForQuery(indexOnlyQuery);
    List<Index> indexList;
    if (index != null) {
        indexList = Collections.singletonList(index);
    } else {
        indexList = Collections.emptyList();
    }
    return indexList;
}
Also used : Index(com.google.storage.onestore.v3.OnestoreEntity.Index)

Example 19 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class LocalDatastoreCostAnalysis method getEntityByPropertyIndexes.

/**
 * Given a set of property names, generates a {@code List} of {@link Index} objects that can be
 * used to generate index rows that would be appear in EntitiesByProperty and
 * EntitiesByPropertyDesc
 *
 * @param propertyNames The property names.
 * @return The indexes.
 */
static List<Index> getEntityByPropertyIndexes(Set<String> propertyNames) {
    List<String> sortedPropertyNames = Ordering.natural().sortedCopy(propertyNames);
    List<Index> indexes = Lists.newArrayList();
    for (String propName : sortedPropertyNames) {
        // EnititiesByProperty
        Index index = new Index();
        index.addProperty(new Index.Property().setName(propName).setDirection(Direction.ASCENDING));
        indexes.add(index);
        // EnititiesByPropertyDesc
        index = new Index();
        index.addProperty(new Index.Property().setName(propName).setDirection(Direction.DESCENDING));
        indexes.add(index);
    }
    return indexes;
}
Also used : Index(com.google.storage.onestore.v3.OnestoreEntity.Index)

Example 20 with Index

use of com.google.storage.onestore.v3.OnestoreEntity.Index in project appengine-java-standard by GoogleCloudPlatform.

the class LocalDatastoreCostAnalysis method changedIndexRows.

/**
 * Determine the number of index rows that need to change when writing {@code newEntity}, assuming
 * {@code oldEntity} represents the current state of the Datastore.
 *
 * @param oldEntity Entity representing the current state in the datastore.
 * @param newEntity Entity representing the desired state in the datastore.
 * @return The number of index rows that need to change.
 */
private int changedIndexRows(EntityProto oldEntity, EntityProto newEntity) {
    // All properties that are unique within the old entity, not all properties that are unique
    // to the old entity. Declaring the specific subtype because we rely on the fact that
    // HashMultimap enforces uniqueness of key-value pairs.
    SetMultimap<String, Property> uniqueOldProperties = HashMultimap.create();
    if (oldEntity != null) {
        for (Property oldProp : oldEntity.propertys()) {
            // A given name may only have one property value on the old entity but multiple values on
            // the new entity. If that's the case, two Properties that are equal will be considered not
            // equal due to different values of the "multiple" attribute. We want these Properties to be
            // considered equal so we hard-code "multiple" to be false in the map.
            oldProp = oldProp.isMultiple() ? oldProp.clone().setMultiple(false) : oldProp;
            uniqueOldProperties.put(oldProp.getName(), oldProp);
        }
    }
    // All properties that are unique within the new entity, not all properties that are unique
    // to the new entity. Declaring the specific subtype because we rely on the fact that
    // HashMultimap enforces uniqueness of key-value pairs.
    SetMultimap<String, Property> uniqueNewProperties = HashMultimap.create();
    // Number of properties per name that have not changed between old and new.
    Multiset<String> unchanged = HashMultiset.create();
    for (Property newProp : newEntity.propertys()) {
        // See the comment in the loop where we populate uniqueOldProperties for an explanation of why
        // we do this.
        newProp = newProp.isMultiple() ? newProp.clone().setMultiple(false) : newProp;
        uniqueNewProperties.put(newProp.getName(), newProp);
        if (uniqueOldProperties.containsEntry(newProp.getName(), newProp)) {
            unchanged.add(newProp.getName());
        }
    }
    // We're going to build Index objects that correspond to the single-property, built-in indexes
    // that the Datastore maintains. In order to do this we need a unique list of all the property
    // names on both the old and new entities.
    Set<String> allPropertyNames = Sets.newHashSet(Iterables.concat(uniqueOldProperties.keySet(), uniqueNewProperties.keySet()));
    Iterable<Index> allIndexes = Iterables.concat(indexManager.getIndexesForKind(Utils.getKind(newEntity.getKey())), getEntityByPropertyIndexes(allPropertyNames));
    Multiset<String> uniqueOldPropertyNames = uniqueOldProperties.keys();
    Multiset<String> uniqueNewPropertyNames = uniqueNewProperties.keys();
    int pathSize = newEntity.getKey().getPath().elementSize();
    int writes = 0;
    for (Index index : allIndexes) {
        // Take ancestor indexes into account.
        // Ancestor doesn't matter for EntityByProperty indexes, and these are the only indexes that
        // have a single property.
        int ancestorMultiplier = index.isAncestor() && index.propertySize() > 1 ? pathSize : 1;
        writes += (calculateWritesForCompositeIndex(index, uniqueOldPropertyNames, uniqueNewPropertyNames, unchanged) * ancestorMultiplier);
    }
    return writes;
}
Also used : Index(com.google.storage.onestore.v3.OnestoreEntity.Index) Property(com.google.storage.onestore.v3.OnestoreEntity.Property)

Aggregations

Index (com.google.storage.onestore.v3.OnestoreEntity.Index)8 OnestoreEntity (com.google.storage.onestore.v3.OnestoreEntity)5 Property (com.google.storage.onestore.v3.OnestoreEntity.Index.Property)5 Order (com.google.apphosting.datastore.DatastoreV3Pb.Query.Order)4 Property (com.google.storage.onestore.v3.OnestoreEntity.Property)4 IndexComponentsOnlyQuery (com.google.appengine.api.datastore.CompositeIndexManager.IndexComponentsOnlyQuery)3 DatastoreV3Pb (com.google.apphosting.datastore.DatastoreV3Pb)3 ByteString (com.google.protobuf.ByteString)3 EntityProto (com.google.storage.onestore.v3.OnestoreEntity.EntityProto)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Map (java.util.Map)3 Test (org.junit.Test)3 Filter (com.google.apphosting.datastore.DatastoreV3Pb.Query.Filter)2 ImmutableList (com.google.common.collect.ImmutableList)2 CompositeIndex (com.google.storage.onestore.v3.OnestoreEntity.CompositeIndex)2 PropertyValue (com.google.storage.onestore.v3.OnestoreEntity.PropertyValue)2 Reference (com.google.storage.onestore.v3.OnestoreEntity.Reference)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2