Removing entries with triggers

Hello, I have a class in my database that accumulates a lot of saved entries extremely quickly I would like to only keep a portion of the entries and remove all the entries from the table without deleting the entire table to retain the most recent 100 entries for example. I would like to delete these rows from a cloud function using a beforeSave trigger. I canā€™t seem to figure out how to get a total count of entries within the class and then remove the amount over my limit. I canā€™t seem to locate the correct solution to my problem with the docs.

Hey @ibn5x

Iā€™ve prepaired an example. It removes all rows before creating new(address - is a filter):

Moralis.Cloud.beforeSave("ItemsOnSale", async function(request) {
  const query = new Moralis.Query("Example");
  const address = request.object.get("address");
  query.equalTo("address", address );
  const objects = await query.find({ useMasterKey: true });
  for (let object of objects) {
    if (object) {
      await objects.destroy(null, {useMasterKey:true}).then(
        () => { 
          logger.info("success");
        },
        (error) => {
          logger.info(error);
        }
      );
    }
  }
});
1 Like

In your case you also need to get length of objects array:

if (objects.lenth > 100) {
  for (let i = 100; i < objects.l; i++) {
   objects[i].destroy(null, {useMasterKey:true})
  }
}

I really appreciate you taking the time to help me. I know this is simple, and I can query and add to Moralis just fine, still, Iā€™m unable to perform this task of filtering, and constraining, then calling a trigger to remove the above threshold entries beforeSave. I hate to admit it, but Iā€™ve spent the better half of three hours, trying still not the desired result. So itā€™s clear I donā€™t understand looking at my cloud function can you see anything that stands out that Iā€™m overlooking?

cloud function

Moralis.Cloud.beforeSave("PlayerPosition", async function(request) {
  const query = new Moralis.Query("PlayerPosition");
  const Player = request.object.get("ethAddress");
  
  query.equalTo("player", Player );
  
  const objects = await query.find({ useMasterKey: true });
  
  if(objects.length > 100){
    for(let i = 100; i < objects.length; i++) {
    objects[i].destroy(null, {useMasterKey:true}).then(
        () => { 
          logger.info("success");
          },
        (error) => {
          logger.info(error);
        }
     );
  }
 }
});

Hi,
What doesnā€™t work as expected, or what error you have if you have an error?

I would try something like this to get more information of what is going on:

Moralis.Cloud.beforeSave("PlayerPosition", async function(request) {
  const query = new Moralis.Query("PlayerPosition");
  const Player = request.object.get("ethAddress");
  
  query.equalTo("player", Player );
  
  const objects = await query.find({ useMasterKey: true });
  logger.info(objects.length);
  
  if(objects.length > 100){
    logger.info("more than 100 objects");
    for(let i = 100; i < objects.length; i++) {
          await objects[i].destroy(null, {useMasterKey:true});
  }
 }
});
1 Like

well the functionality Iā€™m going for requires a trigger beforeSave that checks the length of the entries within the table and if it exceeds 100 entries empty the table retaining only the most recent 100 entries. I canā€™t seem to wrap my head around this concept currently I have the following code which still doesnā€™t function. It continuously allows for the accumulation of entries, which points me in the direction that my method for constraining my query is incorrect, but Iā€™m in no position to make suggestions.

error in Moralis console state : Error: Invalid function: ā€œplayerPositionā€ (Iā€™ve tried to address this with no success)

current cloud function

Moralis.Cloud.beforeSave("PlayerPosition", async function(request) {
  const query = new Moralis.Query("PlayerPosition");
  const player = request.object.get("ethAddress");
  
  query.equalTo("player", player);
  
  const objects = await query.find({ useMasterKey: true });
  
  if(objects.length > 100){
    for(let i = 100; i < objects.length; i++) {
    objects[i].destroy(null, {useMasterKey:true}).then(
        () => { 
          logger.info("success");
          },
        (error) => {
          logger.info(error);
        }
     );
  }
 }
});

Error: Invalid function: ā€œplayerPositionā€ usually means that it has a syntax error.

1 Like

will give it a shot unfortunately Iā€™ve gotten no sleep Iā€™m crashing, shall try it with a fresh set of eyes in a couple of hours or so. Thank you for your time and suggestion. I will report back.

Are you trying to run ā€œPlayerPositionā€? Itā€™s not a cloud function

1 Like

For me it looks like you trying to start ā€œPlayerPositionā€ using Parse.Cloud.run(ā€œPlayerPositionā€). But itā€™s a befoSave trigger, not a function

1 Like

finally awaken. I implemented your suggestion but nothing outputs to the Moralis console. In the google chrome console I now have a failed websocket error. Im combing through my syntax now but I have not come across the error. I will keep at it.

No, Iā€™m only calling it server-side. Although against the advice of the docs I did attempt to call it from the client-side out of frustration a few times before coming to the forum (something like await Moralis.Cloud.run(ā€œplayerPositionā€); which of course did not work.

cloud function

Moralis.Cloud.beforeSave("playerPosition", async function(request) {
  const query = new Moralis.Query("PlayerPosition");
  const Player = request.object.get("ethAddress");
  
  query.equalTo("player", Player);
  
  const objects = await query.find({ useMasterKey: true });
  logger.info(objects.length);
  
  if(objects.length > 100){
    logger.info("more than 100 objects");
    for(let i = 100; i < objects.length; i++) {
    await objects[i].destroy(null, {useMasterKey:true}) 
  }
 }
});

in this case, you may want to use Moralis.Cloud.define instead of Moralis.Cloud.beforeSave and call this cloud function directly when you want to remove old entries.

Now, this is odd. Iā€™m not sure what Iā€™m doing wrong. I took your advice and opted to just define a cloud function and call it every time my user quit the app. Since I was unable to constrain my query properly I decided to jump everything and keep none. Still nothing, I attempted to try and see what was going on with a few console logs but everything fires off as expected except the table does not ā€˜dumpā€™. Iā€™m stumped
defining cloud

Moralis.Cloud.define("playerposition", async function(request) {
  const PlayerQuery = new Moralis.Query("PlayerPosition");
  //const Player = request.object.get("player");
  
  
  //PlayerQuery.equalTo("player", Player);
  
  const objects = await PlayerQuery.find();
   for(let i = 0; i < objects.length; i++) {
    await objects[i].destroy(null, {useMasterKey:true}); 
     return 'inside, should be dumped!';
  }
  return 'entries  Dumped!';
});

calling from clientā€¦

async function dumpPositions() {
    const dumpIt = await Moralis.Cloud.run("playerposition");
    console.log("positions dumped");
    console.log(dumpIt);
}

Im calling the above function from within my logic for game over

async function hitAave(player, aave) {
   let user = Moralis.User.current();
    this.physics.pause();

    player.setTint(0xff0000);

    player.anims.play('turn');
    let highscore = score;
    const HighScore = Moralis.Object.extend("HighScore");
    const highScore = new HighScore();

    highScore.set('player', user.get('ethAddress'));
    highScore.set('score', highscore);

    const RaidHistory = Moralis.Object.extend("RaidHistory");
    const raiderHistory = new RaidHistory();

    raiderHistory.set('player', user.get('ethAddress'));
    raiderHistory.set('score', highscore);
    raiderHistory.set('level', levelReached);
    raiderHistory.set('AavegotchiAnger', angerLevel); 

    await highScore.save();
    await raiderHistory.save();
    dumpPositions();
    console.log("score " + " " + highscore); 
    console.log("score " + " " + raiderHistory); 
    gameOver = true;
}

I appreciate everyoneā€™s patience and assistance, I was finally able to weed out the error with some assistance from you all and finally with @Yomoo coming through for the kill and focusing my direction. I love it here again really appreciate you all assisting me. Iā€™m back to building.

1 Like

Any chance you can post a snippet of your working code?