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