Example usage for com.mongodb.client.model Aggregates project

List of usage examples for com.mongodb.client.model Aggregates project

Introduction

In this page you can find the example usage for com.mongodb.client.model Aggregates project.

Prototype

public static Bson project(final Bson projection) 

Source Link

Document

Creates a $project pipeline stage for the specified projection

Usage

From source file:org.apache.rya.mongodb.aggregation.AggregationPipelineQueryNode.java

License:Apache License

/**
 * Create a pipeline query node based on a StatementPattern.
 * @param collection The collection of triples to query.
 * @param baseSP The leaf node in the query tree.
 *///from  www. j  av a  2  s  .  c  o m
public AggregationPipelineQueryNode(final MongoCollection<Document> collection, final StatementPattern baseSP) {
    this.collection = Preconditions.checkNotNull(collection);
    Preconditions.checkNotNull(baseSP);
    this.varToOriginalName = HashBiMap.create();
    final StatementVarMapping mapping = new StatementVarMapping(baseSP, varToOriginalName);
    this.assuredBindingNames = new HashSet<>(mapping.varNames());
    this.bindingNames = new HashSet<>(mapping.varNames());
    this.pipeline = new LinkedList<>();
    this.pipeline.add(Aggregates.match(getMatchExpression(baseSP)));
    this.pipeline.add(Aggregates.project(mapping.getProjectExpression()));
}

From source file:org.apache.rya.mongodb.aggregation.AggregationPipelineQueryNode.java

License:Apache License

/**
 * Add a join with an individual {@link StatementPattern} to the pipeline.
 * @param sp The statement pattern to join with
 * @return true if the join was successfully added to the pipeline.
 *///from   ww w  .  ja v a 2  s .c  o  m
public boolean joinWith(final StatementPattern sp) {
    Preconditions.checkNotNull(sp);
    // 1. Determine shared variables and new variables
    final StatementVarMapping spMap = new StatementVarMapping(sp, varToOriginalName);
    final NavigableSet<String> sharedVars = new ConcurrentSkipListSet<>(spMap.varNames());
    sharedVars.retainAll(assuredBindingNames);
    // 2. Join on one shared variable
    final String joinKey = sharedVars.pollFirst();
    final String collectionName = collection.getNamespace().getCollectionName();
    Bson join;
    if (joinKey == null) {
        return false;
    } else {
        join = Aggregates.lookup(collectionName, HASHES + "." + joinKey, spMap.hashField(joinKey),
                JOINED_TRIPLE);
    }
    pipeline.add(join);
    // 3. Unwind the joined triples so each document represents a binding
    //   set (solution) from the base branch and a triple that may match.
    pipeline.add(Aggregates.unwind("$" + JOINED_TRIPLE));
    // 4. (Optional) If there are any shared variables that weren't used as
    //   the join key, project all existing fields plus a new field that
    //   tests the equality of those shared variables.
    final BasicDBObject matchOpts = getMatchExpression(sp, JOINED_TRIPLE);
    if (!sharedVars.isEmpty()) {
        final List<Bson> eqTests = new LinkedList<>();
        for (final String varName : sharedVars) {
            final String oldField = valueFieldExpr(varName);
            final String newField = joinFieldExpr(spMap.valueField(varName));
            final Bson eqTest = new Document("$eq", Arrays.asList(oldField, newField));
            eqTests.add(eqTest);
        }
        final Bson eqProjectOpts = Projections.fields(Projections.computed(FIELDS_MATCH, Filters.and(eqTests)),
                Projections.include(JOINED_TRIPLE, VALUES, HASHES, TYPES, LEVEL, TIMESTAMP));
        pipeline.add(Aggregates.project(eqProjectOpts));
        matchOpts.put(FIELDS_MATCH, true);
    }
    // 5. Filter for solutions whose triples match the joined statement
    //  pattern, and, if applicable, whose additional shared variables
    //  match the current solution.
    pipeline.add(Aggregates.match(matchOpts));
    // 6. Project the results to include variables from the new SP (with
    // appropriate renaming) and variables referenced only in the base
    // pipeline (with previous names).
    final Bson finalProjectOpts = new StatementVarMapping(sp, varToOriginalName)
            .getProjectExpression(assuredBindingNames, str -> joinFieldExpr(str));
    assuredBindingNames.addAll(spMap.varNames());
    bindingNames.addAll(spMap.varNames());
    pipeline.add(Aggregates.project(finalProjectOpts));
    return true;
}

From source file:org.apache.rya.mongodb.aggregation.AggregationPipelineQueryNode.java

License:Apache License

/**
 * Add a SPARQL projection or multi-projection operation to the pipeline.
 * The number of documents produced by the pipeline after this operation
 * will be the number of documents entering this stage (the number of
 * intermediate results) multiplied by the number of
 * {@link ProjectionElemList}s supplied here. Empty projections are
 * unsupported; if one or more projections given binds zero variables, then
 * the pipeline will be unchanged and the method will return false.
 * @param projections One or more projections, i.e. mappings from the result
 *  at this stage of the query into a set of variables.
 * @return true if the projection(s) were added to the pipeline.
 *//*w  ww  . ja  v a  2 s .c o  m*/
public boolean project(final Iterable<ProjectionElemList> projections) {
    if (projections == null || !projections.iterator().hasNext()) {
        return false;
    }
    final List<Bson> projectOpts = new LinkedList<>();
    final Set<String> bindingNamesUnion = new HashSet<>();
    Set<String> bindingNamesIntersection = null;
    for (final ProjectionElemList projection : projections) {
        if (projection.getElements().isEmpty()) {
            // Empty projections are unsupported -- fail when seen
            return false;
        }
        final Document valueDoc = new Document();
        final Document hashDoc = new Document();
        final Document typeDoc = new Document();
        final Set<String> projectionBindingNames = new HashSet<>();
        for (final ProjectionElem elem : projection.getElements()) {
            String to = elem.getTargetName();
            // If the 'to' name is invalid, replace it internally
            if (!isValidFieldName(to)) {
                to = replace(to);
            }
            String from = elem.getSourceName();
            // If the 'from' name is invalid, use the internal substitute
            if (varToOriginalName.containsValue(from)) {
                from = varToOriginalName.inverse().get(from);
            }
            projectionBindingNames.add(to);
            if (to.equals(from)) {
                valueDoc.append(to, 1);
                hashDoc.append(to, 1);
                typeDoc.append(to, 1);
            } else {
                valueDoc.append(to, valueFieldExpr(from));
                hashDoc.append(to, hashFieldExpr(from));
                typeDoc.append(to, typeFieldExpr(from));
            }
        }
        bindingNamesUnion.addAll(projectionBindingNames);
        if (bindingNamesIntersection == null) {
            bindingNamesIntersection = new HashSet<>(projectionBindingNames);
        } else {
            bindingNamesIntersection.retainAll(projectionBindingNames);
        }
        projectOpts.add(new Document().append(VALUES, valueDoc).append(HASHES, hashDoc).append(TYPES, typeDoc)
                .append(LEVEL, "$" + LEVEL).append(TIMESTAMP, "$" + TIMESTAMP));
    }
    if (projectOpts.size() == 1) {
        pipeline.add(Aggregates.project(projectOpts.get(0)));
    } else {
        final String listKey = "PROJECTIONS";
        final Bson projectIndividual = Projections.fields(
                Projections.computed(VALUES, "$" + listKey + "." + VALUES),
                Projections.computed(HASHES, "$" + listKey + "." + HASHES),
                Projections.computed(TYPES, "$" + listKey + "." + TYPES), Projections.include(LEVEL),
                Projections.include(TIMESTAMP));
        pipeline.add(Aggregates.project(Projections.computed(listKey, projectOpts)));
        pipeline.add(Aggregates.unwind("$" + listKey));
        pipeline.add(Aggregates.project(projectIndividual));
    }
    assuredBindingNames.clear();
    bindingNames.clear();
    assuredBindingNames.addAll(bindingNamesIntersection);
    bindingNames.addAll(bindingNamesUnion);
    return true;
}

From source file:org.apache.rya.mongodb.aggregation.AggregationPipelineQueryNode.java

License:Apache License

/**
 * Add a SPARQL extension to the pipeline, if possible. An extension adds
 * some number of variables to the result. Adds a "$project" step to the
 * pipeline, but differs from the SPARQL project operation in that
 * 1) pre-existing variables are always kept, and 2) values of new variables
 * are defined by expressions, which may be more complex than simply
 * variable names. Not all expressions are supported. If unsupported
 * expression types are used in the extension, the pipeline will remain
 * unchanged and this method will return false.
 * @param extensionElements A list of new variables and their expressions
 * @return True if the extension was successfully converted into a pipeline
 *  step, false otherwise./*from w ww  .j  a v a2s  .  c  om*/
 */
public boolean extend(final Iterable<ExtensionElem> extensionElements) {
    final List<Bson> valueFields = new LinkedList<>();
    final List<Bson> hashFields = new LinkedList<>();
    final List<Bson> typeFields = new LinkedList<>();
    for (final String varName : bindingNames) {
        valueFields.add(Projections.include(varName));
        hashFields.add(Projections.include(varName));
        typeFields.add(Projections.include(varName));
    }
    final Set<String> newVarNames = new HashSet<>();
    for (final ExtensionElem elem : extensionElements) {
        String name = elem.getName();
        if (!isValidFieldName(name)) {
            // If the field name is invalid, replace it internally
            name = replace(name);
        }
        // We can only handle certain kinds of value expressions; return
        // failure for any others.
        final ValueExpr expr = elem.getExpr();
        final Object valueField;
        final Object hashField;
        final Object typeField;
        if (expr instanceof Var) {
            final String varName = ((Var) expr).getName();
            valueField = "$" + varName;
            hashField = "$" + varName;
            typeField = "$" + varName;
        } else if (expr instanceof ValueConstant) {
            final Value val = ((ValueConstant) expr).getValue();
            valueField = new Document("$literal", val.stringValue());
            hashField = new Document("$literal", SimpleMongoDBStorageStrategy.hash(val.stringValue()));
            if (val instanceof Literal) {
                typeField = new Document("$literal", ((Literal) val).getDatatype().stringValue());
            } else {
                typeField = null;
            }
        } else {
            // if not understood, return failure
            return false;
        }
        valueFields.add(Projections.computed(name, valueField));
        hashFields.add(Projections.computed(name, hashField));
        if (typeField != null) {
            typeFields.add(Projections.computed(name, typeField));
        }
        newVarNames.add(name);
    }
    assuredBindingNames.addAll(newVarNames);
    bindingNames.addAll(newVarNames);
    final Bson projectOpts = Projections.fields(Projections.computed(VALUES, Projections.fields(valueFields)),
            Projections.computed(HASHES, Projections.fields(hashFields)),
            Projections.computed(TYPES, Projections.fields(typeFields)), Projections.include(LEVEL),
            Projections.include(TIMESTAMP));
    pipeline.add(Aggregates.project(projectOpts));
    return true;
}

From source file:org.apache.rya.mongodb.aggregation.AggregationPipelineQueryNode.java

License:Apache License

/**
 * Add a SPARQL filter to the pipeline, if possible. A filter eliminates
 * results that don't satisfy a given condition. Not all conditional
 * expressions are supported. If unsupported expressions are used in the
 * filter, the pipeline will remain unchanged and this method will return
 * false. Currently only supports binary {@link Compare} conditions among
 * variables and/or literals.//w w  w  . ja  v  a  2  s  .c om
 * @param condition The filter condition
 * @return True if the filter was successfully converted into a pipeline
 *  step, false otherwise.
 */
public boolean filter(final ValueExpr condition) {
    if (condition instanceof Compare) {
        final Compare compare = (Compare) condition;
        final Compare.CompareOp operator = compare.getOperator();
        final Object leftArg = valueFieldExpr(compare.getLeftArg());
        final Object rightArg = valueFieldExpr(compare.getRightArg());
        if (leftArg == null || rightArg == null) {
            // unsupported value expression, can't convert filter
            return false;
        }
        final String opFunc;
        switch (operator) {
        case EQ:
            opFunc = "$eq";
            break;
        case NE:
            opFunc = "$ne";
            break;
        case LT:
            opFunc = "$lt";
            break;
        case LE:
            opFunc = "$le";
            break;
        case GT:
            opFunc = "$gt";
            break;
        case GE:
            opFunc = "$ge";
            break;
        default:
            // unrecognized comparison operator, can't convert filter
            return false;
        }
        final Document compareDoc = new Document(opFunc, Arrays.asList(leftArg, rightArg));
        pipeline.add(Aggregates.project(Projections.fields(Projections.computed("FILTER", compareDoc),
                Projections.include(VALUES, HASHES, TYPES, LEVEL, TIMESTAMP))));
        pipeline.add(Aggregates.match(new Document("FILTER", true)));
        pipeline.add(Aggregates
                .project(Projections.fields(Projections.include(VALUES, HASHES, TYPES, LEVEL, TIMESTAMP))));
        return true;
    }
    return false;
}

From source file:org.apache.rya.mongodb.aggregation.AggregationPipelineQueryNode.java

License:Apache License

/**
 * Given that the current state of the pipeline produces data that can be
 * interpreted as triples, add a project step to map each result from the
 * intermediate result structure to a structure that can be stored in the
 * triple store. Does not modify the internal pipeline, which will still
 * produce intermediate results suitable for query evaluation.
 * @param timestamp Attach this timestamp to the resulting triples.
 * @param requireNew If true, add an additional step to check constructed
 *  triples against existing triples and only include new ones in the
 *  result. Adds a potentially expensive $lookup step.
 * @throws IllegalStateException if the results produced by the current
 *  pipeline do not have variable names allowing them to be interpreted as
 *  triples (i.e. "subject", "predicate", and "object").
 *///w ww .jav  a 2 s . co  m
public List<Bson> getTriplePipeline(final long timestamp, final boolean requireNew) {
    if (!assuredBindingNames.contains(SUBJECT) || !assuredBindingNames.contains(PREDICATE)
            || !assuredBindingNames.contains(OBJECT)) {
        throw new IllegalStateException("Current pipeline does not produce "
                + "records that can be converted into triples.\n" + "Required variable names: <" + SUBJECT
                + ", " + PREDICATE + ", " + OBJECT + ">\nCurrent variable names: " + assuredBindingNames);
    }
    final List<Bson> triplePipeline = new LinkedList<>(pipeline);
    final List<Bson> fields = new LinkedList<>();
    fields.add(Projections.computed(SUBJECT, valueFieldExpr(SUBJECT)));
    fields.add(Projections.computed(SUBJECT_HASH, hashFieldExpr(SUBJECT)));
    fields.add(Projections.computed(PREDICATE, valueFieldExpr(PREDICATE)));
    fields.add(Projections.computed(PREDICATE_HASH, hashFieldExpr(PREDICATE)));
    fields.add(Projections.computed(OBJECT, valueFieldExpr(OBJECT)));
    fields.add(Projections.computed(OBJECT_HASH, hashFieldExpr(OBJECT)));
    fields.add(Projections.computed(OBJECT_TYPE,
            ConditionalOperators.ifNull(typeFieldExpr(OBJECT), DEFAULT_TYPE)));
    fields.add(Projections.computed(OBJECT_LANGUAGE, hashFieldExpr(OBJECT)));
    fields.add(Projections.computed(CONTEXT, DEFAULT_CONTEXT));
    fields.add(Projections.computed(STATEMENT_METADATA, DEFAULT_METADATA));
    fields.add(DEFAULT_DV);
    fields.add(Projections.computed(TIMESTAMP, new Document("$literal", timestamp)));
    fields.add(Projections.computed(LEVEL, new Document("$add", Arrays.asList("$" + LEVEL, 1))));
    triplePipeline.add(Aggregates.project(Projections.fields(fields)));
    if (requireNew) {
        // Prune any triples that already exist in the data store
        final String collectionName = collection.getNamespace().getCollectionName();
        final Bson includeAll = Projections.include(SUBJECT, SUBJECT_HASH, PREDICATE, PREDICATE_HASH, OBJECT,
                OBJECT_HASH, OBJECT_TYPE, OBJECT_LANGUAGE, CONTEXT, STATEMENT_METADATA, DOCUMENT_VISIBILITY,
                TIMESTAMP, LEVEL);
        final List<Bson> eqTests = new LinkedList<>();
        eqTests.add(new Document("$eq", Arrays.asList("$$this." + PREDICATE_HASH, "$" + PREDICATE_HASH)));
        eqTests.add(new Document("$eq", Arrays.asList("$$this." + OBJECT_HASH, "$" + OBJECT_HASH)));
        final Bson redundantFilter = new Document("$filter", new Document("input", "$" + JOINED_TRIPLE)
                .append("as", "this").append("cond", new Document("$and", eqTests)));
        triplePipeline.add(Aggregates.lookup(collectionName, SUBJECT_HASH, SUBJECT_HASH, JOINED_TRIPLE));
        final String numRedundant = "REDUNDANT";
        triplePipeline.add(Aggregates.project(Projections.fields(includeAll,
                Projections.computed(numRedundant, new Document("$size", redundantFilter)))));
        triplePipeline.add(Aggregates.match(Filters.eq(numRedundant, 0)));
        triplePipeline.add(Aggregates.project(Projections.fields(includeAll)));
    }
    return triplePipeline;
}

From source file:org.opencb.cellbase.lib.impl.GeneMongoDBAdaptor.java

License:Apache License

@Override
public QueryResult getTfbs(Query query, QueryOptions queryOptions) {
    Bson bsonQuery = parseQuery(query);/*from   w  w w.  jav a  2  s  .  co m*/
    Bson match = Aggregates.match(bsonQuery);

    // We parse user's exclude options, ONLY _id can be added if exists
    Bson includeAndExclude;
    Bson exclude = null;
    if (queryOptions != null && queryOptions.containsKey("exclude")) {
        List<String> stringList = queryOptions.getAsStringList("exclude");
        if (stringList.contains("_id")) {
            exclude = Aggregates.project(Projections.exclude("_id"));
        }
    }
    if (exclude != null) {
        includeAndExclude = Aggregates
                .project(Projections.fields(Projections.excludeId(), Projections.include("transcripts.tfbs")));
    } else {
        includeAndExclude = Aggregates.project(Projections.include("transcripts.tfbs"));
    }

    Bson unwind = Aggregates.unwind("$transcripts");
    Bson unwind2 = Aggregates.unwind("$transcripts.tfbs");

    // This project the three fields of Xref to the top of the object
    Document document = new Document("tfName", "$transcripts.tfbs.tfName");
    document.put("pwm", "$transcripts.tfbs.pwm");
    document.put("chromosome", "$transcripts.tfbs.chromosome");
    document.put("start", "$transcripts.tfbs.start");
    document.put("end", "$transcripts.tfbs.end");
    document.put("strand", "$transcripts.tfbs.strand");
    document.put("relativeStart", "$transcripts.tfbs.relativeStart");
    document.put("relativeEnd", "$transcripts.tfbs.relativeEnd");
    document.put("score", "$transcripts.tfbs.score");
    Bson project = Aggregates.project(document);

    return mongoDBCollection.aggregate(Arrays.asList(match, includeAndExclude, unwind, unwind2, project),
            queryOptions);
}

From source file:org.opencb.cellbase.lib.impl.MongoDBAdaptor.java

License:Apache License

protected QueryResult groupBy(Bson query, String groupByField, String featureIdField, QueryOptions options) {
    if (groupByField == null || groupByField.isEmpty()) {
        return new QueryResult();
    }/*from   www . j  a  v  a 2  s .c  o m*/

    if (groupByField.contains(",")) {
        // call to multiple groupBy if commas are present
        return groupBy(query, Arrays.asList(groupByField.split(",")), featureIdField, options);
    } else {
        Bson match = Aggregates.match(query);
        Bson project = Aggregates.project(Projections.include(groupByField, featureIdField));
        Bson group;
        if (options.getBoolean("count", false)) {
            group = Aggregates.group("$" + groupByField, Accumulators.sum("count", 1));
            return mongoDBCollection.aggregate(Arrays.asList(match, project, group), options);
        } else {
            // Limit the documents passed if count is false
            Bson limit = Aggregates.limit(options.getInt("limit", 10));
            group = Aggregates.group("$" + groupByField,
                    Accumulators.addToSet("features", "$" + featureIdField));
            // TODO change the default "_id" returned by mongodb to id
            return mongoDBCollection.aggregate(Arrays.asList(match, limit, project, group), options);
        }
    }
}

From source file:org.opencb.cellbase.lib.impl.MongoDBAdaptor.java

License:Apache License

protected QueryResult groupBy(Bson query, List<String> groupByField, String featureIdField,
        QueryOptions options) {//  w  w w . java 2  s  .  c om
    if (groupByField == null || groupByField.isEmpty()) {
        return new QueryResult();
    }

    if (groupByField.size() == 1) {
        // if only one field then we call to simple groupBy
        return groupBy(query, groupByField.get(0), featureIdField, options);
    } else {
        Bson match = Aggregates.match(query);
        // add all group-by fields to the projection together with the aggregation field name
        List<String> groupByFields = new ArrayList<>(groupByField);
        groupByFields.add(featureIdField);
        Bson project = Aggregates.project(Projections.include(groupByFields));
        // _id document creation to have the multiple id
        Document id = new Document();
        for (String s : groupByField) {
            id.append(s, "$" + s);
        }
        Bson group;
        if (options.getBoolean("count", false)) {
            group = Aggregates.group(id, Accumulators.sum("count", 1));
            return mongoDBCollection.aggregate(Arrays.asList(match, project, group), options);
        } else {
            // Limit the documents passed if count is false
            Bson limit = Aggregates.limit(options.getInt("limit", 10));
            group = Aggregates.group(id, Accumulators.addToSet("features", "$" + featureIdField));
            // TODO change the default "_id" returned by mongodb to id
            return mongoDBCollection.aggregate(Arrays.asList(match, limit, project, group), options);
        }
    }
}

From source file:org.opencb.cellbase.lib.impl.XRefMongoDBAdaptor.java

License:Apache License

@Override
public QueryResult nativeGet(Query query, QueryOptions options) {
    Bson bson = parseQuery(query);/*ww w . j  a v  a  2 s.c  om*/
    Bson match = Aggregates.match(bson);

    Bson project = Aggregates.project(Projections.include("transcripts.xrefs"));
    Bson unwind = Aggregates.unwind("$transcripts");
    Bson unwind2 = Aggregates.unwind("$transcripts.xrefs");

    // This project the three fields of Xref to the top of the object
    Document document = new Document("id", "$transcripts.xrefs.id");
    document.put("dbName", "$transcripts.xrefs.dbName");
    document.put("dbDisplayName", "$transcripts.xrefs.dbDisplayName");
    Bson project1 = Aggregates.project(document);

    return mongoDBCollection.aggregate(Arrays.asList(match, project, unwind, unwind2, project1), options);
}