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