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 std::set<std::string_view> setVariablesNames;
303 std::vector<std::pair<const char *, Variable *>> duplicates;
304 for (
auto &it: varList) {
305 if (setVariablesNames.count(it.second->name()) > 0) {
306 duplicates.push_back(it);
309 appendSetVariable(setVariables, it.second->name(), it.first);
310 setVariablesNames.insert(it.second->name());
316 for (
auto &it: duplicates) {
321 bson_t exprDoc, matchArr;
323 BSON_APPEND_DOCUMENT_BEGIN(matchStage,
"$expr", &exprDoc);
324 BSON_APPEND_ARRAY_BEGIN(&exprDoc,
"$eq", &matchArr);
325 BSON_APPEND_UTF8(&matchArr,
"0", varValue.c_str());
326 BSON_APPEND_UTF8(&matchArr,
"1", it.first);
327 bson_append_array_end(&exprDoc, &matchArr);
328 bson_append_document_end(matchStage, &exprDoc);
335 static void nonTransitiveLookup(
340 bool b_isTaxonomicProperty = (definedProperty &&
341 tripleStore.
vocabulary->isTaxonomicProperty(definedProperty->iri()));
342 char arrIndexStr[16];
343 const char *arrIndexKey;
346 bool b_skipInputGroundings =
false;
349 b_skipInputGroundings =
true;
352 b_skipInputGroundings =
true;
353 for (
auto &exprTerm: {
363 b_skipInputGroundings =
false;
371 bson_t lookupArray, letDoc;
373 BSON_APPEND_UTF8(lookupStage,
"from", tripleStore.
tripleCollection->name().data());
374 BSON_APPEND_UTF8(lookupStage,
"as",
"next");
375 if (!b_skipInputGroundings) {
377 BSON_APPEND_DOCUMENT_BEGIN(lookupStage,
"let", &letDoc);
380 BSON_APPEND_UTF8(&letDoc,
"v_VARS",
"$$v_VARS");
382 BSON_APPEND_UTF8(&letDoc,
"v_VARS",
"$v_VARS");
384 bson_append_document_end(lookupStage, &letDoc);
386 BSON_APPEND_ARRAY_BEGIN(lookupStage,
"pipeline", &lookupArray);
388 Pipeline lookupPipeline(&lookupArray);
390 auto matchStage = lookupPipeline.appendStageBegin(
"$match");
391 if (b_skipInputGroundings) {
396 bson_t andArray, tripleDoc, variablesDoc;
397 BSON_APPEND_ARRAY_BEGIN(matchStage,
"$and", &andArray);
399 BSON_APPEND_DOCUMENT_BEGIN(&andArray,
"0", &tripleDoc);
402 bson_append_document_end(&andArray, &tripleDoc);
408 std::make_pair(b_isTaxonomicProperty ?
"$p" :
"$p*", lookupData.
expr->
propertyTerm()),
409 std::make_pair(b_isTaxonomicProperty ?
"$o*" :
"$o", lookupData.
expr->
objectTerm())
418 bson_uint32_to_string(arrIndex++,
419 &arrIndexKey, arrIndexStr,
sizeof arrIndexStr);
420 BSON_APPEND_DOCUMENT_BEGIN(&andArray, arrIndexKey, &variablesDoc);
421 appendMatchVariable(&variablesDoc, it.first,
var->name(), lookupData);
422 bson_append_document_end(&andArray, &variablesDoc);
425 bson_append_array_end(matchStage, &andArray);
427 lookupPipeline.appendStageEnd(matchStage);
431 bson_append_array_end(lookupStage, &lookupArray);
446 pipeline.
unset(
"next");
449 static void transitiveLookup(
454 bool b_isTaxonomicProperty = (definedProperty &&
455 tripleStore.
vocabulary->isTaxonomicProperty(definedProperty->iri()));
457 bool b_objectIsKnownGrounded = lookupData.
expr->
objectTerm()->isVariable() &&
459 std::static_pointer_cast<Variable>(lookupData.
expr->
objectTerm())->name()) >
461 bool b_startWithSubject = lookupData.
expr->
subjectTerm()->isGround() || !b_objectIsKnownGrounded;
463 auto startTerm = (b_startWithSubject ?
465 auto endTerm = (b_startWithSubject ?
469 bson_t restrictSearchDoc;
471 BSON_APPEND_UTF8(lookupStage,
"from", tripleStore.
tripleCollection->name().data());
473 auto startString = (
Atomic *) startTerm.get();
474 BSON_APPEND_UTF8(lookupStage,
"startWith", startString->stringForm().data());
476 auto startVariable = (
Variable *) startTerm.get();
478 BSON_APPEND_UTF8(lookupStage,
"startWith", startValue.c_str());
480 KB_WARN(
"Ignoring term {} with invalid type for graph lookup.", *startTerm);
482 BSON_APPEND_UTF8(lookupStage,
"connectToField", b_startWithSubject ?
"s" :
"o");
483 BSON_APPEND_UTF8(lookupStage,
"connectFromField", b_startWithSubject ?
"o" :
"s");
484 BSON_APPEND_UTF8(lookupStage,
"as",
"t_paths");
485 BSON_APPEND_UTF8(lookupStage,
"depthField",
"depth");
487 BSON_APPEND_DOCUMENT_BEGIN(lookupStage,
"restrictSearchWithMatch", &restrictSearchDoc);
490 (b_isTaxonomicProperty ?
"p" :
"p*"),
497 bson_append_document_end(lookupStage, &restrictSearchDoc);
502 bson_t setSortedDoc, sortArrayDoc, sortByDoc;
504 BSON_APPEND_DOCUMENT_BEGIN(setSortedStage,
"t_sorted", &setSortedDoc);
505 BSON_APPEND_DOCUMENT_BEGIN(&setSortedDoc,
"$sortArray", &sortArrayDoc);
506 BSON_APPEND_UTF8(&sortArrayDoc,
"input",
"$t_paths");
507 BSON_APPEND_DOCUMENT_BEGIN(&sortArrayDoc,
"$sortArray", &sortByDoc);
508 BSON_APPEND_INT32(&sortByDoc,
"depth", 1);
509 bson_append_document_end(&sortArrayDoc, &sortByDoc);
510 bson_append_document_end(&setSortedDoc, &sortArrayDoc);
511 bson_append_document_end(setSortedStage, &setSortedDoc);
516 BSON_APPEND_UTF8(setNext,
"next",
"$t_sorted");
520 bson_t setStartOperation, setStartArr;
522 BSON_APPEND_DOCUMENT_BEGIN(setStart,
"start", &setStartOperation);
523 BSON_APPEND_ARRAY_BEGIN(&setStartOperation,
"$arrayElemAt", &setStartArr);
524 BSON_APPEND_UTF8(&setStartArr,
"0",
"$next");
525 BSON_APPEND_INT32(&setStartArr,
"1", 0);
526 bson_append_array_end(&setStartOperation, &setStartArr);
527 bson_append_document_end(setStart, &setStartOperation);
531 pipeline.
unset(
"t_paths");
532 pipeline.
unset(
"t_sorted");
541 bson_t exprDoc, orArr, ungroundedMatch, groundedMatch, notArray;
542 BSON_APPEND_DOCUMENT_BEGIN(matchEnd,
"$expr", &exprDoc);
543 BSON_APPEND_ARRAY_BEGIN(&exprDoc,
"$or", &orArr);
545 BSON_APPEND_DOCUMENT_BEGIN(&orArr,
"0", &ungroundedMatch);
546 BSON_APPEND_ARRAY_BEGIN(&ungroundedMatch,
"$not", ¬Array);
548 BSON_APPEND_UTF8(¬Array,
"0", (
std::string(
"$") + varKey).c_str());
549 bson_append_array_end(&ungroundedMatch, ¬Array);
550 bson_append_document_end(&orArr, &ungroundedMatch);
552 BSON_APPEND_DOCUMENT_BEGIN(&orArr,
"1", &groundedMatch);
553 MongoTerm::append(&groundedMatch, (b_startWithSubject ?
"next.o" :
"next.s"), endTerm);
554 bson_append_document_end(&orArr, &groundedMatch);
556 bson_append_array_end(&exprDoc, &orArr);
557 bson_append_document_end(matchEnd, &exprDoc);
559 MongoTerm::append(matchEnd, (b_startWithSubject ?
"next.o" :
"next.s"), endTerm);
566 pipeline.
unset(
"next");
572 auto propertyTerm = std::static_pointer_cast<Atomic>(lookupData.
expr->
propertyTerm());
573 definedProperty = tripleStore.
vocabulary->getDefinedProperty(propertyTerm->stringForm());
576 bool b_isTransitiveProperty = (definedProperty && definedProperty->hasFlag(
578 if (b_isTransitiveProperty)
579 transitiveLookup(pipeline, tripleStore, lookupData, definedProperty);
581 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