6 #include "knowrob/storage/mongo/MongoTriplePattern.h"
7 #include "knowrob/storage/mongo/MongoTerm.h"
8 #include "knowrob/storage/mongo/Pipeline.h"
13 #define MONGO_OPERATOR_LTE "$lte"
14 #define MONGO_OPERATOR_GTE "$gte"
15 #define MONGO_OPERATOR_LT "$lt"
16 #define MONGO_OPERATOR_GT "$gt"
17 #define MONGO_OPERATOR_NEQ "$ne"
21 bool b_isTaxonomicProperty,
22 const std::shared_ptr<ImportHierarchy> &importHierarchy)
23 : document_(create(tripleExpression, b_isTaxonomicProperty, importHierarchy)) {
28 bool b_isTaxonomicProperty,
29 const std::shared_ptr<ImportHierarchy> &importHierarchy) {
30 auto selectorDoc = bson_new();
31 append(selectorDoc, tripleExpression, b_isTaxonomicProperty, importHierarchy);
37 bool b_isTaxonomicProperty,
38 const std::shared_ptr<ImportHierarchy> &importHierarchy) {
44 (b_isTaxonomicProperty ?
"p" :
"p*"),
49 (b_isTaxonomicProperty ?
"o*" :
"o"),
62 const std::shared_ptr<ImportHierarchy> &importHierarchy) {
67 auto graphString = gt.grounded();
71 std::vector<TermPtr> childrenNames;
72 for (
auto &child: importHierarchy->getImports(graphString->stringForm())) {
75 if (childrenNames.empty()) {
78 childrenNames.push_back(graphString);
93 KB_WARN(
"graph term {} has unexpected type", *gt);
102 if (!((u.has_grounding() && u.grounded()->asBoolean()) || u.has_variable())) {
121 KB_WARN(
"agent term {} has unexpected type", *at);
127 BSON_APPEND_DOCUMENT_BEGIN(selectorDoc,
"agent", &agentDoc);
128 BSON_APPEND_BOOL(&agentDoc,
"$exists",
false);
129 bson_append_document_end(selectorDoc, &agentDoc);
142 KB_WARN(
"confidence term {} has unexpected type", *ct);
148 static const bool allowNullValues =
true;
149 static auto b_occasional = std::make_shared<Integer>(
static_cast<int32_t
>(
true));
150 static auto b_always = std::make_shared<Integer>(
static_cast<int32_t
>(
false));
152 auto et = &tripleExpression.
endTerm();
155 if (!((o.has_grounding() && o.grounded()->asBoolean()) || o.has_variable())) {
169 if (bt->has_grounding()) {
177 if (et->has_grounding()) {
188 switch (operatorType) {
205 static inline void appendSetVariable(bson_t *doc, std::string_view varName, std::string_view newValue) {
208 bson_t condDoc, condArray, notOperator, notArray;
211 BSON_APPEND_DOCUMENT_BEGIN(doc, varKey.c_str(), &condDoc);
212 BSON_APPEND_ARRAY_BEGIN(&condDoc,
"$cond", &condArray);
214 BSON_APPEND_DOCUMENT_BEGIN(&condArray,
"0", ¬Operator);
215 BSON_APPEND_ARRAY_BEGIN(¬Operator,
"$not", ¬Array);
216 BSON_APPEND_UTF8(¬Array,
"0", varValue.c_str());
217 bson_append_array_end(¬Operator, ¬Array);
218 bson_append_document_end(&condArray, ¬Operator);
220 BSON_APPEND_UTF8(&condArray,
"1", newValue.data());
221 BSON_APPEND_UTF8(&condArray,
"2", varValue.c_str());
223 bson_append_array_end(&condDoc, &condArray);
224 bson_append_document_end(doc, &condDoc);
227 static inline void appendMatchVariable(bson_t *doc,
228 std::string_view fieldValue,
229 std::string_view varName,
232 const auto varLetValue =
std::string(
"$$") + varKey;
233 const auto matchOperator = (fieldValue.back() ==
'*' ?
"$in" :
"$eq");
234 bson_t exprDoc, orArr, notDoc, notArr, matchDoc, matchArr;
236 BSON_APPEND_DOCUMENT_BEGIN(doc,
"$expr", &exprDoc);
241 BSON_APPEND_ARRAY_BEGIN(&exprDoc, matchOperator, &matchArr);
242 BSON_APPEND_UTF8(&matchArr,
"0", varLetValue.c_str());
243 BSON_APPEND_UTF8(&matchArr,
"1", fieldValue.data());
244 bson_append_array_end(&exprDoc, &matchArr);
247 BSON_APPEND_ARRAY_BEGIN(&exprDoc,
"$or", &orArr);
250 BSON_APPEND_DOCUMENT_BEGIN(&orArr,
"0", ¬Doc);
251 BSON_APPEND_ARRAY_BEGIN(¬Doc,
"$not", ¬Arr);
252 BSON_APPEND_UTF8(¬Arr,
"0", varLetValue.c_str());
253 bson_append_array_end(¬Doc, ¬Arr);
254 bson_append_document_end(&orArr, ¬Doc);
257 BSON_APPEND_DOCUMENT_BEGIN(&orArr,
"1", &matchDoc);
258 BSON_APPEND_ARRAY_BEGIN(&matchDoc, matchOperator, &matchArr);
259 BSON_APPEND_UTF8(&matchArr,
"0", varLetValue.c_str());
260 BSON_APPEND_UTF8(&matchArr,
"1", fieldValue.data());
261 bson_append_array_end(&matchDoc, &matchArr);
262 bson_append_document_end(&orArr, &matchDoc);
264 bson_append_array_end(&exprDoc, &orArr);
266 bson_append_document_end(doc, &exprDoc);
271 const std::set<std::string_view> &knownGroundedVariables) {
272 std::list<std::pair<const char *, Variable *>> varList;
277 if (objectVar && !objectVar->isVariable() && expr.
objectVariable()) {
284 std::make_pair(
"$next.o", objectVar),
285 std::make_pair(
"$next.graph", expr.
graphTerm().get()),
288 std::make_pair(
"$next.scope.time.since", expr.
beginTerm().get()),
289 std::make_pair(
"$next.scope.time.until", expr.
endTerm().get()),
296 if (knownGroundedVariables.count(
var->name()) > 0)
continue;
297 varList.emplace_back(it.first,
var);
300 if (!varList.empty()) {
302 for (
auto &it: varList) {
303 appendSetVariable(setVariables, it.second->name(), it.first);
309 static void nonTransitiveLookup(
314 bool b_isTaxonomicProperty = (definedProperty &&
315 tripleStore.
vocabulary->isTaxonomicProperty(definedProperty->iri()));
316 char arrIndexStr[16];
317 const char *arrIndexKey;
320 bool b_skipInputGroundings =
false;
323 b_skipInputGroundings =
true;
326 b_skipInputGroundings =
true;
327 for (
auto &exprTerm: {
337 b_skipInputGroundings =
false;
345 bson_t lookupArray, letDoc;
347 BSON_APPEND_UTF8(lookupStage,
"from", tripleStore.
tripleCollection->name().data());
348 BSON_APPEND_UTF8(lookupStage,
"as",
"next");
349 if (!b_skipInputGroundings) {
351 BSON_APPEND_DOCUMENT_BEGIN(lookupStage,
"let", &letDoc);
354 BSON_APPEND_UTF8(&letDoc,
"v_VARS",
"$$v_VARS");
356 BSON_APPEND_UTF8(&letDoc,
"v_VARS",
"$v_VARS");
358 bson_append_document_end(lookupStage, &letDoc);
360 BSON_APPEND_ARRAY_BEGIN(lookupStage,
"pipeline", &lookupArray);
362 Pipeline lookupPipeline(&lookupArray);
364 auto matchStage = lookupPipeline.appendStageBegin(
"$match");
365 if (b_skipInputGroundings) {
370 bson_t andArray, tripleDoc, variablesDoc;
371 BSON_APPEND_ARRAY_BEGIN(matchStage,
"$and", &andArray);
373 BSON_APPEND_DOCUMENT_BEGIN(&andArray,
"0", &tripleDoc);
376 bson_append_document_end(&andArray, &tripleDoc);
382 std::make_pair(b_isTaxonomicProperty ?
"$p" :
"$p*", lookupData.
expr->
propertyTerm()),
383 std::make_pair(b_isTaxonomicProperty ?
"$o*" :
"$o", lookupData.
expr->
objectTerm())
392 bson_uint32_to_string(arrIndex++,
393 &arrIndexKey, arrIndexStr,
sizeof arrIndexStr);
394 BSON_APPEND_DOCUMENT_BEGIN(&andArray, arrIndexKey, &variablesDoc);
395 appendMatchVariable(&variablesDoc, it.first,
var->name(), lookupData);
396 bson_append_document_end(&andArray, &variablesDoc);
399 bson_append_array_end(matchStage, &andArray);
401 lookupPipeline.appendStageEnd(matchStage);
405 bson_append_array_end(lookupStage, &lookupArray);
420 pipeline.
unset(
"next");
423 static void transitiveLookup(
428 bool b_isTaxonomicProperty = (definedProperty &&
429 tripleStore.
vocabulary->isTaxonomicProperty(definedProperty->iri()));
431 bool b_objectIsKnownGrounded = lookupData.
expr->
objectTerm()->isVariable() &&
433 std::static_pointer_cast<Variable>(lookupData.
expr->
objectTerm())->name()) >
435 bool b_startWithSubject = lookupData.
expr->
subjectTerm()->isGround() || !b_objectIsKnownGrounded;
437 auto startTerm = (b_startWithSubject ?
439 auto endTerm = (b_startWithSubject ?
443 bson_t restrictSearchDoc;
445 BSON_APPEND_UTF8(lookupStage,
"from", tripleStore.
tripleCollection->name().data());
447 auto startString = (
Atomic *) startTerm.get();
448 BSON_APPEND_UTF8(lookupStage,
"startWith", startString->stringForm().data());
450 auto startVariable = (
Variable *) startTerm.get();
452 BSON_APPEND_UTF8(lookupStage,
"startWith", startValue.c_str());
454 KB_WARN(
"Ignoring term {} with invalid type for graph lookup.", *startTerm);
456 BSON_APPEND_UTF8(lookupStage,
"connectToField", b_startWithSubject ?
"s" :
"o");
457 BSON_APPEND_UTF8(lookupStage,
"connectFromField", b_startWithSubject ?
"o" :
"s");
458 BSON_APPEND_UTF8(lookupStage,
"as",
"t_paths");
459 BSON_APPEND_UTF8(lookupStage,
"depthField",
"depth");
461 BSON_APPEND_DOCUMENT_BEGIN(lookupStage,
"restrictSearchWithMatch", &restrictSearchDoc);
464 (b_isTaxonomicProperty ?
"p" :
"p*"),
471 bson_append_document_end(lookupStage, &restrictSearchDoc);
476 bson_t setSortedDoc, sortArrayDoc, sortByDoc;
478 BSON_APPEND_DOCUMENT_BEGIN(setSortedStage,
"t_sorted", &setSortedDoc);
479 BSON_APPEND_DOCUMENT_BEGIN(&setSortedDoc,
"$sortArray", &sortArrayDoc);
480 BSON_APPEND_UTF8(&sortArrayDoc,
"input",
"$t_paths");
481 BSON_APPEND_DOCUMENT_BEGIN(&sortArrayDoc,
"$sortArray", &sortByDoc);
482 BSON_APPEND_INT32(&sortByDoc,
"depth", 1);
483 bson_append_document_end(&sortArrayDoc, &sortByDoc);
484 bson_append_document_end(&setSortedDoc, &sortArrayDoc);
485 bson_append_document_end(setSortedStage, &setSortedDoc);
490 BSON_APPEND_UTF8(setNext,
"next",
"$t_sorted");
494 bson_t setStartOperation, setStartArr;
496 BSON_APPEND_DOCUMENT_BEGIN(setStart,
"start", &setStartOperation);
497 BSON_APPEND_ARRAY_BEGIN(&setStartOperation,
"$arrayElemAt", &setStartArr);
498 BSON_APPEND_UTF8(&setStartArr,
"0",
"$next");
499 BSON_APPEND_INT32(&setStartArr,
"1", 0);
500 bson_append_array_end(&setStartOperation, &setStartArr);
501 bson_append_document_end(setStart, &setStartOperation);
505 pipeline.
unset(
"t_paths");
506 pipeline.
unset(
"t_sorted");
515 bson_t exprDoc, orArr, ungroundedMatch, groundedMatch, notArray;
516 BSON_APPEND_DOCUMENT_BEGIN(matchEnd,
"$expr", &exprDoc);
517 BSON_APPEND_ARRAY_BEGIN(&exprDoc,
"$or", &orArr);
519 BSON_APPEND_DOCUMENT_BEGIN(&orArr,
"0", &ungroundedMatch);
520 BSON_APPEND_ARRAY_BEGIN(&ungroundedMatch,
"$not", ¬Array);
522 BSON_APPEND_UTF8(¬Array,
"0", (
std::string(
"$") + varKey).c_str());
523 bson_append_array_end(&ungroundedMatch, ¬Array);
524 bson_append_document_end(&orArr, &ungroundedMatch);
526 BSON_APPEND_DOCUMENT_BEGIN(&orArr,
"1", &groundedMatch);
527 MongoTerm::append(&groundedMatch, (b_startWithSubject ?
"next.o" :
"next.s"), endTerm);
528 bson_append_document_end(&orArr, &groundedMatch);
530 bson_append_array_end(&exprDoc, &orArr);
531 bson_append_document_end(matchEnd, &exprDoc);
533 MongoTerm::append(matchEnd, (b_startWithSubject ?
"next.o" :
"next.s"), endTerm);
540 pipeline.
unset(
"next");
546 auto propertyTerm = std::static_pointer_cast<Atomic>(lookupData.
expr->
propertyTerm());
547 definedProperty = tripleStore.
vocabulary->getDefinedProperty(propertyTerm->stringForm());
550 bool b_isTransitiveProperty = (definedProperty && definedProperty->hasFlag(
552 if (b_isTransitiveProperty)
553 transitiveLookup(pipeline, tripleStore, lookupData, definedProperty);
555 nonTransitiveLookup(pipeline, tripleStore, lookupData, definedProperty);
#define MONGO_OPERATOR_GTE
#define MONGO_OPERATOR_LT
#define MONGO_OPERATOR_NEQ
#define MONGO_OPERATOR_LTE
#define MONGO_OPERATOR_GT
static std::shared_ptr< knowrob::Atom > Tabled(std::string_view stringForm)
static constexpr std::string_view ORIGIN_ANY
static std::shared_ptr< Numeric > falseAtom()
auto objectOperator() const
auto & propertyTerm() const
auto & subjectTerm() const
auto & objectVariable() const
auto & isOccasionalTerm() const
auto & isUncertainTerm() const
auto & objectTerm() const
uint32_t numVariables() const override
auto & perspectiveTerm() const
auto & confidenceTerm() const
static void append(bson_t *doc, const char *key, const TermPtr &term, const char *queryOperator=nullptr, bool matchNullValue=false, bool includeVariables=false)
static std::string variableKey(const std::string_view &varName)
static bson_t * create(const TriplePattern &tripleExpression, bool b_isTaxonomicProperty, const std::shared_ptr< ImportHierarchy > &importHierarchy)
MongoTriplePattern(const TriplePattern &tripleExpression, bool b_isTaxonomicProperty, const std::shared_ptr< ImportHierarchy > &importHierarchy)
static const char * getOperatorString(knowrob::FilterType operatorType)
static void appendEpistemicSelector(bson_t *selectorDoc, const TriplePattern &tripleExpression)
static void appendTimeSelector(bson_t *selectorDoc, const TriplePattern &tripleExpression)
static void append(bson_t *selectorDoc, const TriplePattern &tripleExpression, bool b_isTaxonomicProperty, const std::shared_ptr< ImportHierarchy > &importHierarchy)
static void setTripleVariables(Pipeline &pipeline, const TriplePattern &expr, const std::set< std::string_view > &knownGroundedVariables)
static void appendGraphSelector(bson_t *selectorDoc, const TriplePattern &tripleExpression, const std::shared_ptr< ImportHierarchy > &importHierarchy)
void appendStageEnd(bson_t *stage)
bson_t * appendStageBegin()
void matchEmptyArray(std::string_view arrayKey)
void unwind(std::string_view field, bool preserveNullAndEmptyArrays=false)
void unset(std::string_view field)
void lookupTriple(Pipeline &pipeline, const TripleStore &tripleStore, const TripleLookupData &lookupData)
std::shared_ptr< Property > PropertyPtr
std::shared_ptr< Term > TermPtr
std::set< std::string_view > knownGroundedVariables
const TriplePattern * expr
bool mayHasMoreGroundings
std::shared_ptr< knowrob::mongo::Collection > tripleCollection
std::shared_ptr< knowrob::Vocabulary > vocabulary