Using Parse Javascript SDK Query GeoPoint withinMiles - javascript

I am creating a Parse App and I want to be able to get all objects within a certain distance of a single object using GeoPoints. Seems simple, but the following code returns [] (No matches):
app.get('/photos', function(req, res) {
var Photo = Parse.Object.extend("Photo");
var query = new Parse.Query(Photo);
query.equalTo("owner", Parse.User.current());
query.find({
success: function(results) {
// Do something with the returned Parse.Object values
//res.send(results);
var photo = results[0];
// Create a query for places
var Photo = Parse.Object.extend("Photo");
var query = new Parse.Query(Photo);
// Interested in photos taken near this photo.
query.withinMiles("coordinates", photo.coordinates, 500000);
// Final list of objects
query.find({
success: function(photoObjects) {
res.send(photoObjects);
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
});
Oddly, if I change the line
query.withinMiles("coordinates", photo.coordinates, 500000);
to
query.near("coordinates", photo.coordinates);
then it works without a hitch and returns all photos (Every single one has a GeoPoint within about a 5 mile radius of all the others in the sample data set, so I used a maxDistance of 500000 to test the extent of the issue).
The problem is I need to be able to limit to a specific radius, which is what I thought the "withinMiles" was doing. Any ideas what I may be doing wrong?

In case someone is finding this and shares my troubles, the following was the issue:
I was assuming that all "columns" of data objects in parse are treated as attributes. i.e. - You can access them using the . operator (photo.coordinates).
In fact, you must access them via photo.get("coordinates") to get the actual objects contained within the data structure.
Not sure why the above scenario was working in the case of the "near" function, but nonetheless the behavior works correctly when I started using the get accessor method for the Parse data objects.

Related

Parse.com fetch collection

I'm new to Parse.com, and I want to ask, how display all items from collection. This is my code:
var User = Parse.Object.extend("User");
var TestCollection = Parse.Collection.extend({
model: User
});
var collection = new TestCollection();
collection.fetch({
reset: false,
success: function(collection) {
document.write('<h1>' + "Users:<br>" + '</h1>');
document.write('<table><tr>');
document.write('<td>User name</td>');
document.write('<td>Email</td></tr>');
collection.each(function(user) {
document.write('<tr><td>'+user.get('username')+'</td>');
document.write('<td>'+user.get('email')+'</td>');
document.write('</tr></table>');
});
},
error: function(collection, error) {
alert("Error: " + error.code + " " + error.message);
}
});
In this way, I got all items, but the webpage always reload without stop. Help please. Thanks in advance!
Once you've fixed up the document.write() issues, you'll also need to be aware that the User (and Role and Installation) classes are special in Parse.
To query them, you can't do it the way you have. Delete the line where you're extending with "User" as that won't work.
Change your collection to the following:
var TestCollection = Parse.Collection.extend({
model: Parse.User
});
The way you have done it is correct for any classes you create, but you have to use the inbuilt definitions for the inbuilt Parse classes.

Obtain Data from two parse classes based on column in one table

I have to Parse Classes in my data browser, 'Details' and 'Content'. The 'Details' class has the following --> 'objectId', 'uuid' and 'proximity'. The 'Content' class has 'objectId', 'descId' and 'offer'.
I have created a web UI using the Javascript SDK so when the user enters the uuid, proximity and offer, uuid and proximity get stored in the 'Details' class, on success I then get the objectId of the newly created object. I then store that objectId in the 'Content' class under descId and the offer that was inputted by the user.
My problem is I have a html table that I need to populate, so I need to pull the data from both classes. The uuid and proximity from 'Details' and the offer from 'Content' so I need to do this in one query. This is my reason for storing the 'Details' objectId in the 'Content' class as a type of foreign key.
I am stuck at this cross roads and have tried include etc but I am just trying things and I'm not sure what I need to do. If anyone can help, perhaps show me a sample, I'd greatly appreciate it
Here is my js save code:
//Creating Beacon Content Parse Object
var iBeaconContent = Parse.Object.extend("Content");
var beaconContent = new iBeaconContent();
//Creating Object to save to iBeacon Description Table
var iBeaconDescription = Parse.Object.extend("Details");
var beaconDescription = new iBeaconDescription();
beaconDescription.set("uuid", tdUuid.children("input[type=text]").val().toString());
beaconDescription.set("proximity", parseInt(tdProximity.children($('prox')).val().toString()));
beaconDescription.save(null, {
success: function(beaconDescriptionObject) {
var query = new Parse.Query("Details");
query.equalTo("uuid", tdUuid.children("input[type=text]").val().toString());
query.find({
success: function(results) {
objectId = results[0].id;
beaconContent.set("descId", objectId);
beaconContent.set("offer", tdOffer.children("input[type=text]").val().toString());
beaconContent.save(null, {
success: function(object) {
document.location.reload(true);
}, error: function(beaconContent, error) {
}
});
}
});
},
error: function(error) {
}
});
NEW JAVASCRIPT
var BeaconDetail = Parse.Object.extend("Details");
var BeaconContent = Parse.Object.extend("Content");
var innerQuery = new Parse.Query(BeaconDetail);
innerQuery.exists("descId");
var query = Parse.Query(BeaconDetail);
query.matchesQuery("objectId", innerQuery);
query.find({
success:function(beaconContent){
alert("Success----lenght: " + beaconContent.length);
}
})
Sound like you need to use a compound query or relationship query. Here are some links
https://docs.parseplatform.org/js/guide/#relational-queries
https://docs.parseplatform.org/js/guide/#compound-queries
https://parse.com/questions/compound-relational-queries
An example of a query from two classes is as follows
It would also be good to see the code, would help give a more relative answer.
CODE
var lotsOfWins = new Parse.Query("Player");
lotsOfWins.greaterThan("wins", 150);
var fewWins = new Parse.Query("Player");
fewWins.lessThan("wins", 5);
var mainQuery = Parse.Query.or(lotsOfWins, fewWins);
mainQuery.find({
success: function(results) {
// results contains a list of players that either have won a lot of games or won only a few games.
},
error: function(error) {
// There was an error.
}
});
If I understand correctly, your Content class contains a pointer to your Details class in the descId property, and you want to be able to query based on some Details fields and return both objects?
NOTE: I must point out that descId is a very poorly named property that will just cause confusion. If it is a pointer, just give it a name like desc, leave off the Id suffix.
Anyway, if that is what you want:
var query = new Parse.Query("Content");
var uuid = tdUuid.children("input[type=text]").val().toString();
var proximity = parseInt(tdProximity.children($('prox')).val().toString());
// consider logging those two variable to confirm they're what you want
// query properties of a pointer
query.equalTo("descId.uuid", uuid);
query.equalTo("descId.proximity", proximity);
// include the pointer in the output
query.include("descId");
query.find({
success: function(beaconContent) {
alert("Success -- length: " + beaconContent.length);
// sample output of first result:
var content = beaconContent[0];
var detail = content.get("descId");
console.log("uuid", detail.get("uuid"));
console.log("proximity", detail.get("proximity"));
console.log("offer", content.get("offer"));
}
});

Search for case insensitive data from Parse using javascript

I am using Parse.com and access it using Javascript. I want to search data in such a manner that it will not search for case sensitive like if i search abc then it will give abc, Abc, ABC,aBc etc all. but currently it gives only abc.
JavaScript:
var search_data="Temp";
var product = Parse.Object.extend("product");
var query = new Parse.Query(product);
query.contains("name",search_data);
query.find({
success: function(results) {
console.log("Total Product Found : "+results.length);
printSearchProducts(results,query); //custom method to print product detail
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
Actual Result: Temp1,Temp2,Temp3,ProductTemp3,Temp4Product etc.
Required Result: Temp1,Temp2,Temp3,ProductTemp3,Temp4Product,temp5,producttemp6,TEMP7,tEMp8 etc.
For that you can use Parse.Query's matches() function, which even it's not indicated in its documentation page, but you can use it like this :
query.matches(key, value, 'i');
Hope that can help.
At this point in time you aren't able to perform case insensitive searches via a query.
A very easy workaround for this however, is to store a lower case version of the field you need to do this query on.
Creating The Item
var Product = Parse.Object.extend("product");
var newProduct = new Product();
var productName = "Temp4Product";
newProduct.set("name",productName);
newProduct.set("name_lowercase",productName.toLowerCase());
newProduct.save();
Performing the query
var search_data="Temp";
var product = Parse.Object.extend("product");
var query = new Parse.Query(product);
query.contains("name_lowercase",search_data.toLowerCase());
query.find({
success: function(results) {
console.log("Total Product Found : "+results.length);
printSearchProducts(results,query); //custom method to print product detail
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
Note in the above example I've used the string.toLowerCase() function, however there may be a more appropriate function for you to use. Basically you want to find a way to "simplify" your data so that you can perform the appropriate query.
The solutions that suggest an extra stored field with the lowercase value have the disadvantage of requiring additional storage. The matches method works, but has a minor performance cost.
A better workaround that avoids both of these issues is to use an aggregate with the $toLower expression in a projection.
I have solved this issue.
I remove constraint query.contains("name",search_data); and apply manual search using java script inside printSearchProducts method like:
var search_data="Temp";
var product = Parse.Object.extend("product");
var query = new Parse.Query(product);
query.limit(500);
query.find({
success: function(results) {
printSearchProducts(results,query,search_data);
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
printSearchProducts Method Where search manually via Java Script.
function printSearchProducts(results,query,search_data) {
var counter = results.length;
var productName = '',i=0;
search_data = search_data.toLowerCase();
if(counter){
while(i<counter){
var found = -1;
productName = results[i].get("name");
var lower_name = productName.replace(/[^a-zA-Z]/g,'_').toLowerCase();
found = lower_name.indexOf(search_data);
if(found>=0) {
//Access or print the required result here
}
i++;
}
}
}

Parse with Meteor JS

I am using Parse (http://parse.com) inside a Meteor Application (http://meteor.com)
I am trying to query my Parse Database from the server side, and everything is fine until I get to the query.
I get the following error:
[TypeError: Cannot call method 'getItem' of undefined]
This is what my code looks like: [I have even tried query.find()]
var VITxUser = Parse.Object.extend("VITxMaster");
var query = new Parse.Query(VITxUser);
query.equalTo("fbid", "1231212");
//no errors till here
query.first({
success: function(object) {
if (!object){
//insert the user
var GameScore = Parse.Object.extend("VITxMaster");
var gameScore = new GameScore();
gameScore.set("fbid", profile.id);
gameScore.set("registrationNumber", "12DEV0000");
gameScore.set("VITevents", "true");
gameScore.save(null, {
success: function(gameScore) {
// Execute any logic that should take place after the object is saved.
alert('New object created with objectId: ' + gameScore.id + 'and fbid: ' + profile.id);
},
error: function(gameScore, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and description.
alert('Failed to create new object, with error code: ' + error.description);
}
});
}
else{
console.log("found object");
console.log(object.get("registrationNumber"));
}
}
});
I can't see a reference to getItem in your code. I suspect however that the issue is due to meteor's variable scoping. Basically in Meteor each file is variable scoped. So you if you had two files file1.js and file2.js they would be wrapped around in a function(){..}.
You would need to remove the variable scoping by not using var to define your variables. Particularly the one's you want to be accessible globally (in other files)

jQuery Appending unwanted data

Some jQuery function in my code is inserting the string:
jQuery15206649508478338135_1314906667378
into user-provided feedback. This is happening from multiple forms and it's getting stored in the database, which is really annoying our users. One sample of such code:
$(".sendFeedback").live("click", function() {
var feedbackText = $(".feedbackText:visible").val();
var errorElement = $(".feedbackError:first");
if (isEmptyTrimmed(feedbackText)) {
errorOut(errorElement, language.pleaseEnterFeedbackText);
return false;
}
var sendFeedback = { email : userSettings.email, firstName : "",lastName : "",primaryRole : "", description : "<br />Feedback text: <pre>" + feedbackText + "</pre>",
sendNotification : false, isPartner : false , formType : 3};
callService("sendFeedback", sendFeedback);
currentMessage = language.thankYouForTheFeedback;
loadScreenByHash("mainScreen");
});
function callService(serviceName, data, callbackFunction) {
var json = $.toJSON(data);
json = "{ " + serviceName + ": " + json + " }";
$.post(serviceUrl, json,
function(response) {
if (callbackFunction) {
callbackFunction(response);
}
}, 'json').error(function() {
if (callbackFunction) {
callbackFunction();
}
});
}
The callService function directs to a Java server, so I'm doubting it's getting inserted there. The java server writes to the DB, so I'm pretty sure it's getting inserted in the javascript code.
It happens other places as well, and they follow the same formula: read user input with .val(), pass to callService (sometimes through additional JS function). A sample of the output data:
I created a quiz but can not figure out how to run it for my class.
there are no buttons that say run
quizjQuery15206649508478338135_1314906667378? Customer Name
I've also seen it appended at the end of a string. Let me know if anyone has seen this before.
I found the cause of the problem. User data was entered, sent to the database, but the database was not set for UTF-8. The problem occurred every time the character encoding was messed up in the database. When the database returned garbage, it would trigger the string to be added.
Changing the database encoding solved this problem.

Categories

Resources