Google Datastore combine (union) multiple sets of entity results to achieve OR condition

后端 未结 2 1940
迷失自我
迷失自我 2020-12-06 23:07

I am working with NodeJS on Google App Engine with the Datastore database.

Due to the fact that Datastore does not have support the OR operator, I need to run multip

2条回答
  •  悲哀的现实
    2020-12-06 23:52

    Here is the solution I created based on the advice provided in the accepted answer.

    /*History JSON*/
    module.exports.treqHistoryJSON = function(req, res) {
      if (!req.user) {
        req.user = {};
        res.json();
        return;
      }
    
      //Set Requester username
      const loggedin_username = req.user.userName;
    
      //Get records matching Requester OR Dataowner
      //Google Datastore OR Conditions are not supported
      //Workaround separate parallel queries get records matching Requester and Dataowner then combine results
      async.parallel({
        //Get entity keys matching Requester
        requesterKeys: function(callback) {
          getKeysOnly('TransferRequest', 'requester_username', loggedin_username, (treqs_by_requester) => {
            //Callback pass in response as parameter
            callback(null, treqs_by_requester)
          });
        },
        //Get entity keys matching Dataowner
        dataownerKeys: function(callback) {
          getKeysOnly('TransferRequest', 'dataowner_username', loggedin_username, (treqs_by_dataowner) => {
            callback(null, treqs_by_dataowner)
          });
        }
      }, function(err, getEntities) {
        if (err) {
          console.log('Transfer Request History JSON unable to get entity keys Transfer Request. Error message: ', err);
          return;
        } else {
          //Combine two arrays of entity keys into a single de-duplicated array of entity keys
          let entity_keys_union = unionEntityKeys(getEntities.requesterKeys, getEntities.dataownerKeys);
          //Get key values from entity key 'symbol' object type
          let entity_keys_only = entity_keys_union.map((ent) => {
            return ent[datastore.KEY];
          });
          //Pass in array of entity keys to get full entities
          datastore.get(entity_keys_only, function(err, entities) {
            if(err) {
              console.log('Transfer Request History JSON unable to lookup multiple entities by key for Transfer Request. Error message: ', err);
              return;
              //If query works and returns any entities
            } else {
              processEntitiesToDisplay(res, entities);
            }
          });
        }
      });
    
    };
    
    /*
     * Get keys-only entities by kind and property
     * @kind string name of kind
     * @property_type string property filtering by in query
     * @filter_value string of filter value to match in query
     * getEntitiesCallback callback to collect results
     */
    function getKeysOnly(kind, property_type, filter_value, getEntitiesCallback) {
      //Create datastore query
      const keys_query = datastore.createQuery(kind);
      //Set query conditions
      keys_query.filter(property_type, filter_value);
      //Select KEY only
      keys_query.select('__key__');
      datastore.runQuery(keys_query, function(err, entities) {
        if(err) {
          console.log('Get Keys Only query unable to return data results. Error message: ', err);
          return;
        } else {
          getEntitiesCallback(entities);
        }
      });
    }
    
    /*
     * Union two arrays of entity keys de-duplicate based on ID value
     * @arr1 array of entity keys
     * @arr2 array of entity keys
     */
    function unionEntityKeys(arr1, arr2) {
      //Create new array
      let arr3 = [];
      //For each element in array 1
      for(let i in arr1) {
        let shared = false;
          for (let j in arr2)
            //If ID in array 1 is same as array 2 then this is a duplicate
            if (arr2[j][datastore.KEY]['id'] == arr1[i][datastore.KEY]['id']) {
              shared = true;
              break;
            }
          //If IDs are not the same add element to new array
          if(!shared) {
            arr3.push(arr1[i])
          }
        }
      //Concat array 2 and new array 3
      arr3 = arr3.concat(arr2);
      return arr3;
    }
    

提交回复
热议问题