List of usage examples for com.mongodb.client.model Aggregates lookup
public static <TExpression> Bson lookup(final String from, @Nullable final List<Variable<TExpression>> let, final List<? extends Bson> pipeline, final String as)
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 .j a va 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
/** * 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"). *//*from ww w . j a va 2 s.c o 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; }