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);
}
);
}
}
});
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});
}
}
});
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.
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
For me it looks like you trying to start āPlayerPositionā using Parse.Cloud.run(āPlayerPositionā). But itās a befoSave trigger, not a function
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.
Any chance you can post a snippet of your working code?