docs: function makeMdlMongo(modelHandle, sModelName, oModel) {
      var modelDoc = modelHandle.modelDocs[sModelName];
      var oMdl = {
          bitindex: getDomainBitIndexSafe(modelDoc.domain, oModel),
          domain: modelDoc.domain,
          modelname: sModelName,
          description: modelDoc.domain_description
      };
      var categoryDescribedMap = {};
      oMdl.bitindex = getDomainBitIndexSafe(modelDoc.domain, oModel);
      oMdl.category = modelDoc._categories.map(cat => cat.category);
      oMdl.categoryDescribed = [];
      modelDoc._categories.forEach(cat => {
          oMdl.categoryDescribed.push({
              name: cat.category,
              description: cat.category_description
          });
          categoryDescribedMap[cat.category] = cat;
      });
      oMdl.category = modelDoc._categories.map(cat => cat.category);
      /* // rectify category
       oMdl.category = oMdl.category.map(function (cat: any) {
           if (typeof cat === "string") {
               return cat;
           }
           if (typeof cat.name !== "string") {
               console.log("Missing name in object typed category in " + JSON.stringify(cat) + " in model " + sModelName);
               process.exit(-1);
               //throw new Error('Domain ' + oMdl.domain + ' already loaded while loading ' + sModelName + '?');
           }
           categoryDescribedMap[cat.name] = cat;
           oMdl.categoryDescribed.push(cat);
           return cat.name;
       });
       */
      // add the categories to the rules
      oMdl.category.forEach(function (category) {
          insertRuleIfNotPresent(oModel.mRules, {
              category: "category",
              matchedString: category,
              type: IMatch.EnumRuleType.WORD,
              word: category,
              lowercaseword: category.toLowerCase(),
              bitindex: oMdl.bitindex,
              wordType: IMatch.WORDTYPE.CATEGORY,
              bitSentenceAnd: oMdl.bitindex,
              _ranking: 0.95
          }, oModel.seenRules);
      });
      // add synonanym for the categories to the
      modelDoc._categories.forEach(cat => {
          addSynonyms;
      });
      if (oModel.domains.indexOf(oMdl.domain) < 0) {
          debuglog("***********here mdl" + JSON.stringify(oMdl, undefined, 2));
          throw new Error('Domain ' + oMdl.domain + ' already loaded while loading ' + sModelName + '?');
      }
      /*
      // check properties of model
      Object.keys(oMdl).sort().forEach(function (sProperty) {
          if (ARR_MODEL_PROPERTIES.indexOf(sProperty) < 0) {
              throw new Error('Model property "' + sProperty + '" not a known model property in model of domain ' + oMdl.domain + ' ');
          }
      });
      */
      // consider streamlining the categories
      oModel.rawModels[oMdl.domain] = oMdl;
      oModel.full.domain[oMdl.domain] = {
          description: oMdl.description,
          categories: categoryDescribedMap,
          bitindex: oMdl.bitindex
      };
      // check that
      // check that members of wordindex are in categories,
      /* oMdl.wordindex = oModelDoc.oMdl.wordindex || [];
       oMdl.wordindex.forEach(function (sWordIndex) {
           if (oMdl.category.indexOf(sWordIndex) < 0) {
               throw new Error('Model wordindex "' + sWordIndex + '" not a category of domain ' + oMdl.domain + ' ');
           }
       });
       */
      /*
      oMdl.exactmatch = oMdl.exactmatch || [];
      oMdl.exactmatch.forEach(function (sExactMatch) {
          if (oMdl.category.indexOf(sExactMatch) < 0) {
              throw new Error('Model exactmatch "' + sExactMatch + '" not a category of domain ' + oMdl.domain + ' ');
          }
      });
      */
      oMdl.columns = modelDoc.columns; // oMdl.columns || [];
      oMdl.columns.forEach(function (sExactMatch) {
          if (oMdl.category.indexOf(sExactMatch) < 0) {
              throw new Error('Model column "' + sExactMatch + '" not a category of domain ' + oMdl.domain + ' ');
          }
      });
      // add relation domain -> category
      var domainStr = MetaF.Domain(oMdl.domain).toFullString();
      var relationStr = MetaF.Relation(Meta.RELATION_hasCategory).toFullString();
      var reverseRelationStr = MetaF.Relation(Meta.RELATION_isCategoryOf).toFullString();
      oMdl.category.forEach(function (sCategory) {
          var CategoryString = MetaF.Category(sCategory).toFullString();
          oModel.meta.t3[domainStr] = oModel.meta.t3[domainStr] || {};
          oModel.meta.t3[domainStr][relationStr] = oModel.meta.t3[domainStr][relationStr] || {};
          oModel.meta.t3[domainStr][relationStr][CategoryString] = {};
          oModel.meta.t3[CategoryString] = oModel.meta.t3[CategoryString] || {};
          oModel.meta.t3[CategoryString][reverseRelationStr] = oModel.meta.t3[CategoryString][reverseRelationStr] || {};
          oModel.meta.t3[CategoryString][reverseRelationStr][domainStr] = {};
      });
      // add a precice domain matchrule
      insertRuleIfNotPresent(oModel.mRules, {
          category: "domain",
          matchedString: oMdl.domain,
          type: IMatch.EnumRuleType.WORD,
          word: oMdl.domain,
          bitindex: oMdl.bitindex,
          bitSentenceAnd: oMdl.bitindex,
          wordType: IMatch.WORDTYPE.DOMAIN,
          _ranking: 0.95
      }, oModel.seenRules);
      // add domain synonyms
      if (modelDoc.domain_synonyms && modelDoc.domain_synonyms.length > 0) {
          addSynonyms(modelDoc.domain_synonyms, "domain", modelDoc.domain, oMdl.bitindex, oMdl.bitindex, IMatch.WORDTYPE.DOMAIN, oModel.mRules, oModel.seenRules);
          addSynonyms(modelDoc.domain_synonyms, "domain", modelDoc.domain, getDomainBitIndexSafe(DOMAIN_METAMODEL, oModel), getDomainBitIndexSafe(DOMAIN_METAMODEL, oModel), IMatch.WORDTYPE.FACT, oModel.mRules, oModel.seenRules);
          // TODO: synonym have to be added as *FACT* for the metamodel!
      }
      ;
      /*
          // check the tool
          if (oMdl.tool && oMdl.tool.requires) {
              var requires = Object.keys(oMdl.tool.requires || {});
              var diff = _.difference(requires, oMdl.category);
              if (diff.length > 0) {
                  console.log(` ${oMdl.domain} : Unkown category in requires of tool: "` + diff.join('"') + '"');
                  process.exit(-1);
              }
              var optional = Object.keys(oMdl.tool.optional);
              diff = _.difference(optional, oMdl.category);
              if (diff.length > 0) {
                  console.log(` ${oMdl.domain} : Unkown category optional of tool: "` + diff.join('"') + '"');
                  process.exit(-1);
              }
              Object.keys(oMdl.tool.sets || {}).forEach(function (setID) {
                  var diff = _.difference(oMdl.tool.sets[setID].set, oMdl.category);
                  if (diff.length > 0) {
                      console.log(` ${oMdl.domain} : Unkown category in setId ${setID} of tool: "` + diff.join('"') + '"');
                      process.exit(-1);
                  }
              });
  
              // extract tools an add to tools:
              oModel.tools.filter(function (oEntry) {
                  if (oEntry.name === (oMdl.tool && oMdl.tool.name)) {
                      console.log("Tool " + oMdl.tool.name + " already present when loading " + sModelName);
                      //throw new Error('Domain already loaded?');
                      process.exit(-1);
                  }
              });
          } else {
              oMdl.toolhidden = true;
              oMdl.tool.requires = { "impossible": {} };
          }
          // add the tool name as rule unless hidden
          if (!oMdl.toolhidden && oMdl.tool && oMdl.tool.name) {
              insertRuleIfNotPresent(oModel.mRules, {
                  category: "tool",
                  matchedString: oMdl.tool.name,
                  type: IMatch.EnumRuleType.WORD,
                  word: oMdl.tool.name,
                  bitindex: oMdl.bitindex,
                  bitSentenceAnd : oMdl.bitindex,
                  wordType : IMatch.WORDTYPE.TOOL,
                  _ranking: 0.95
              }, oModel.seenRules);
          };
          if (oMdl.synonyms && oMdl.synonyms["tool"]) {
              addSynonyms(oMdl.synonyms["tool"], "tool", oMdl.tool.name, oMdl.bitindex,
              oMdl.bitindex, IMatch.WORDTYPE.TOOL, oModel.mRules, oModel.seenRules);
          };
          */
      // add synsonym for the domains
      // add synonyms for the categories
      modelDoc._categories.forEach(cat => {
          if (cat.category_synonyms && cat.category_synonyms.length > 0) {
              if (oModel.full.domain[oMdl.domain].categories[cat.category]) {
                  oModel.full.domain[oMdl.domain].categories[cat.category].category_synonyms = cat.category_synonyms;
              }
              addSynonyms(cat.category_synonyms, "category", cat.category, oMdl.bitindex, oMdl.bitindex, IMatch.WORDTYPE.CATEGORY, oModel.mRules, oModel.seenRules);
              // add synonyms into the metamodel domain
              addSynonyms(cat.category_synonyms, "category", cat.category, getDomainBitIndexSafe(DOMAIN_METAMODEL, oModel), getDomainBitIndexSafe(DOMAIN_METAMODEL, oModel), IMatch.WORDTYPE.FACT, oModel.mRules, oModel.seenRules);
          }
      });
      // add operators
      // add fillers
      if (oModel.domains.indexOf(oMdl.domain) < 0) {
          throw Error('missing domain registration for ' + oMdl.domain);
      }
      //oModel.domains.push(oMdl.domain);
      oModel.category = oModel.category.concat(oMdl.category);
      oModel.category.sort();
      oModel.category = oModel.category.filter(function (string, index) {
          return oModel.category[index] !== oModel.category[index + 1];
      });
      return oMdl;
  }