Here is a cloud function for the query:
Parse.Cloud.define("newProfiles", async (request) => {
const token = request.user.getSessionToken();
//get requesting user's profile
const usrProfQuery = new Parse.Query("PrsProfile");
usrProfQuery.equalTo("objectId", request.user.id);
const usrProfile = await usrProfQuery.first({ sessionToken: token });
if (!usrProfile) {
throw "current user profile not found";
}
//basic query criteria common for all specific queries
const minAge = request.user.get("minA");
const maxAge = request.user.get("maxA");
const ori = usrProfile.get("o");
const partnerOri = usrProfile.get("po");
//Gender: 0 - woman, 1 - notDefined, 2 - man
const usrGender = usrProfile.get("gn");
if (usrGender == 1) {
throw "current user gender is not defined";
}
//max distance
const maxDistance = request.user.get("maxD");
const currentLoc = usrProfile.get("gp");
//search type queries
var specificQueries = []
// ------------ dating specific query ------------
const usrDate = usrProfile.get("da");
//const usrOns = usrProfile.get("on");
if (usrDate != null && maxDistance != null) {
const dateQuery = new Parse.Query("PrsProfile");
//distance in km
dateQuery.withinKilometers("gp", currentLoc, maxDistance, false);
//basic data
dateQuery.lessThanOrEqualTo("ag", maxAge);
dateQuery.greaterThanOrEqualTo("ag", minAge);
if (partnerOri != null) {
dateQuery.equalTo("o", partnerOri);
}
//dateQuery.equalTo("po", ori);
dateQuery.containedIn("po", [null, ori]);
//genders are defined for each specific query separately
if (usrGender == 0) {
//search for users looking for notDefined or women
dateQuery.lessThanOrEqualTo("da", 1);
} else if (usrGender == 2) {
//search for users looking for notDefined or men
dateQuery.greaterThanOrEqualTo("da", 1);
}
if (usrDate != 1) {
//if current user defines specific gender, add it to constraints
dateQuery.equalTo("gn", usrDate);
}
if (usrProfile.get("on") == true) {
dateQuery.equalTo("on", true);
}
//bloom filter
//Inverted values - Array of "available Integers"
//const bloomFilter = request.user.get("daBlm");
//dummy generation of an array
const bloomFilter = dummyArray(128000);
//const bloomFilter = request.user.filter;
dateQuery.containedIn("bf", bloomFilter);
//dateQuery.explain()
const results = await dateQuery.find({ sessionToken: token });
return results;
} else {
throw "not enough inputs to run a query";
}
});
function generating fake “empty” bloom filter. Let’s called it “available bits array” as it is full from integers 0…128000 in above example for a fresh user that still did not remove any key.
function dummyArray(N) {
var a=Array(N),b=0;
while(b<N) a[b++]=b;
return a;
}
when user creates account, it creates User document and Profile document, where in the profile document should be a field with hashed objectId into a one Int… that is the “bf” field in dateQuery.containedIn("bf", bloomFilter);
apart from the bloom filter validation containedIn/By it behaves as intended. I am just a bit confused how to check that any value in “bf” is not in the bloomFilter array.
- It works well when there is only one Int in “bf” (not array) and using containedIn.
- It scans the document if I check containedIn(“bf”, bloomFilter) where “bf” is and array of [Int, Int]
-
containedBy does produce for me strange behaviour as seen in my last post. It feels more like I should feed an array of ranges to it and it will return documents where “bf” values are within or outside these ranges…