Making News Feed using Parse.com queries - javascript

I'm trying to create a news feed based on my friends and myself activities using Parse queries. I have a collection called "MeFollow" [has columns "me" "followUser"] which shows ppl I follow and another collection called "Activity" which stores toUser, fromUser, type, content.
this is how I find my followers:
var myFollowers = new Parse.Query("MeFollow");
myFollowers.equalTo("me", Parse.User.current());
but I can't find my friends activities using next query:
var friendsActivity = new Parse.Query("Activity");
friendsActivity.equalTo("fromUser", myFollowers.followUser);
my activities works fine:
var myActivity = new Parse.Query("Activity");
myActivity.equalTo("fromUser", Parse.User.current());
here is the main query:
var mainQuery = Parse.Query.or(myActivity, friendsActivity);
mainQuery.include("fromUser");
mainQuery.include("productId");
mainQuery.descending("createdAt");
mainQuery.find({
success: function(results) {
console.log(results);
response.success(results);
},
error: function(error) {
response.error(error);
// There was an error.
}
});
I think I cannot do "myFollowers.followUser"! Does anyone know how can I make this possible?
PS: I'm doing this in cloud code so it is javascript

You can't use myFollowers.followUser because myFollowers returns objects that show relations between me and followUser, not the followUser objects itself.
You should use matchesKeyInQuery like:
var friendsActivity = new Parse.Query("Activity");
friendsActivity.matchesKeyInQuery("fromUser", "followUser",myFollowers);
You can check this docs which is not easily accessed in the main documentation: https://www.parse.com/docs/js/api/symbols/Parse.Query.html#matchesKeyInQuery

Related

Firebase Web retrieve data

I have the following db structure in firebase
I'm trying to grab data that belongs to a specific user id (uid). The documentation has the following example:
firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) {
var username = snapshot.val().username;
// ...
});
But how can I retrieve data from my example without knowing the unique key for each object?
Update:
I tried a new approach by adding the user id as the main key and each child object has it's own unique id.
Now the challenge is how to get the value of "title".
firebase.database().ref('/tasks/').orderByChild('uid').equalTo(userUID)
Well that is pretty straightforward. Then you can use it like this:
return firebase.database().ref('/tasks/').orderByChild('uid').equalTo(userUID).once('value').then(function(snapshot) {
var username = snapshot.val().username;
// ...
});
Of course you need to set userUID.
It is query with some filtering. More on Retrieve Data - Firebase doc
Edit: Solution for new challenge is:
var ref = firebase.database().ref('/tasks/' + userUID);
//I am doing a child based listener, but you can use .once('value')...
ref.on('child_added', function(data) {
//data.key will be like -KPmraap79lz41FpWqLI
addNewTaskView(data.key, data.val().title);
});
ref.on('child_changed', function(data) {
updateTaskView(data.key, data.val().title);
});
ref.on('child_removed', function(data) {
removeTaskView(data.key, data.val().title);
});
Note that this is just an example.

Does Parse.com permit the inclusion of pointers inside a relation query?

I have the following many-to-many relationship in my Parse.com application:
Bit ↔ Message
The following fetches related messages from a 'Bit' object:
const query = new Parse.Query('Bit');
query.include('participants');
query.include('user');
query.equalTo('objectId', req.query.bitId);
const promise = query.first().then(function(bit) {
return new Promise(function(resolve) {
const relation = bit.relation('messages');
relation.query().find().then(function(messages) {
resolve(messages);
});
});
});
*Note: messages is a relation column type not a pointer type.
The result inside messages is an array that contains all of the related messages for that bit. Each message contains a pointer to a User called sender. Is it possible to include this User object in the query result? It would be nice if I could use the include() method on a relational query like so:
relation.include('sender');
You can qualify a relation's query as you would any other query. (Also, you've got some superfluous promise code in the OP. I cleaned that up a little, but the point of the answer is on the commented line)...
var query = new Parse.Query('Bit');
query.include('participants');
query.include('user');
query.equalTo('objectId', req.query.bitId);
var promise = query.first().then(function(bit) {
var relationalQuery = bit.relation('messages').query();
relationalQuery.include("sender"); // <-- the point
return relationalQuery().find();
}).then(function(messages) {
return resolve(messages);
});

Use of Geolocation in Parse's Cloud Code

I have a user class with two types of users - customers, and vendors. There is a column (GeoPoint) called vendorLocation in user table which has coordinates of the vendor's shop but is left blank (null) for the customers.
When a customer places an order, a new object is created in the Order Class in which I store the address location as a GeoPoint. I want to find the vendor closest to him. I tried to write a cloud code but kept facing the same error over and over.
Parse.Cloud.define("assignVendor", function(request, response){
var orderObjectId = request.params.orderObjectId;
var query= new Parse.Query("Order")
query.equalTo("objectId", orderObjectId);
query.first({
success: function(order){
//order is the newly created parse order object
//console.log("Order object found"+ order.get("orderNumber"));
var userGeoPoint=new Parse.GeoPoint();
//This is the problematic line
userGeoPoint = order.get("customerLocation");
var Query = new Parse.Query(Parse.User);
Query.exists("vendorLocation");
Query.near("vendorLocation", userGeoPoint);
console.log("Reached here");
Query.find({
success: function(results){
var chemist= results[0];
response.success("found "+vendor.get("profileName"));
order.put("vendorLocation", chemist);
order.save(null, {
success: function(result) {response.success("Saved")},
error: function(error) {console.log("Failed at save")} });
},
error:function(error){console.log("Cant find a suitable vendor")}
});
}, error:function(error){console.log("cant find the ");}
});
});
The error shown in cloud code console.
E2015-10-06T11:23:40.858Z]v13 Ran cloud function assignVendor for user 4otr3l7YwG with:
Input: {"orderObjectId":"OS5siGRXYW"}
Result: TypeError: Cannot call method 'get' of undefined
at e.Query.find.success (main.js:25:53)
at e.<anonymous> (Parse.js:14:27927)
at e.s (Parse.js:14:26859)
at e.n.value (Parse.js:14:26278)
at e.s (Parse.js:14:26987)
at e.n.value (Parse.js:14:26278)
at e.s (Parse.js:14:26987)
at e.n.value (Parse.js:14:26278)
at e.<anonymous> (Parse.js:14:26931)
at e.s (Parse.js:14:26859)
I2015-10-06T11:23:40.924Z]Reached here
The android code
HashMap atMap=new HashMap<>();
atMap.put("orderObjectId", "OS5siGRXYW");
ParseCloud.callFunctionInBackground("assignVendor", atMap, new FunctionCallback<String>() {
#Override
public void done(String value, ParseException e) {
if (e!=null){Log.d("failed ", +e.getCode()+e.getMessage());} else {Log.d("s", value);}
}
});
Error showed in android code is exactly the same as console, so I havnt posted it again. Error number is '141'
Here's some help tracking down the cause of your problem.
make absolutely sure that the order number is being passed correctly
and that the order with the object Id you are passing exists.
you may run into problems when directly assigning nested callbacks
to the first() function. It is better to use then() to string promises together.
it is better to use get() than to use first() when trying to
find a single object, as you should get an object not found error
if get() returns nothing, preventing the cannot call method get
error.
Let's clean up your code and see if it helps:
Parse.Cloud.define("assignVendor", function(request, response){
var fetchedOrder;
var orderObjectId = request.params.orderObjectId;
console.log("orderObjectId = " + orderObjectId);
var orderQuery= new Parse.Query("Order")
orderQuery.get(orderObjectId)
.then(function(order){
fetchedOrder = order;
console.log("Order object found"+ fetchedOrder.get("orderNumber"));
userGeoPoint = fetchedOrder.get("customerLocation");
var userQuery = new Parse.Query(Parse.User);
userQuery.near("vendorLocation", userGeoPoint);
return userQuery.first();
})
.then(function(chemist){
order.put("vendorLocation", chemist);
return order.save();
})
.then(function(){
response.success("Success!");
}, function (error){
console.error(JSON.stringify(error));
response.error(error);
});
});
Notes:
You dont need to define a new Parse.Geopoint before getting
customerLocation. You are just reassigning a variable there.
You dont need to check if the vendorLocation exists before
comparing it to the userGeoPoint. If it doesnt exist, it simply
wont get returned when using near
I would advise using response.success only at the end all your
promise thread
After userQuery.find(), I believe that order does not exist in that
context so I've set it as a function variable.
There is no need to use results[0], simply use first()

Parse.com multiple relational queries

Here is a question for parse.com gurus.
I am using Parse Javascript API and trying to execute a query over 2 Pointers and cannot get it to work.
So i have following classes: Posts, Users, Groups. Posts has Pointer to Users. Users has a Pointer to Groups.
I need to get all POSTS, where a USER belongs to GROUP, which name starts with "Admin". Here is my code that doesn't work:
var Posts = Parse.Object.extend("Posts");
var Users = Parse.Object.extend("Users");
var Groups = Parse.Object.extend("Groups");
var query = new Parse.Query(Posts);
var innerQueryUsers = new Parse.Query(Users);
var innerQueryGroups = new Parse.Query(Groups);
innerQueryGroups.startsWith("name", "Admin");
innerQueryUsers.matchesQuery("group", innerQueryGroups);
query.matchesQuery("user", innerQueryUsers);
query.find({
success: function(data) {
},
error: function(error){
// here i get error: {code: 102, message: "bad type for $inQuery"}
}
});
Anybody have an idea how to do it right?
Edit - This can be done in one (untested) query by combining a group query and a post query with the same user query...
function postsInGroup(name) {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("name", name);
var userQuery = new Parse.Query(Parse.User);
userQuery.matchesQuery("group", groupQuery);
var postQuery = new Parse.Query("Post");
postQuery.matchesQuery("user", userQuery);
return postQuery.find();
}
Call it like this...
postsInGroup("Admin").then(function(posts) {
console.log(JSON.stringify(posts));
}, function(error) {
console.log(JSON.stringify(error));
});
Its not clear what savings there is between this approach and first querying the group. It's likely that parse.com runs the inner queries much as you would. The difference in readability is a matter of taste.

Get list of objects not yet in a relation in Parse.com Angular javascript

I am building an AngularJS CRUD site to add data to Parse.com to be used by mobile apps that will read it. (The CRUD is easier to do on a real keyboard due to the amount of data added.) First step is to create and save the Child objects (Ingredients and Steps), and then to create and save a Recipe object that has a Relation to the Ingredients and Steps. I need to use Relation and not Pointers for these. (because I may need this to be many to many in future)
Here's my problem: writing the query to find any Ingredients and Steps that were created that are NOT yet part of a relation, to find the ones to be added to a new recipe.
The examples in the Javascript SDK don't show this scenario, they only show a query for a relation that exists, but does not have an additional attribute on the related item (comments for posts where post doesn't have an image).
Recipe has ingredients, a Relation<Ingredient>, and steps, a Relation<Step>.
This doesn't work to get the Ingredients that are not yet related to a Recipe.
var Recipe = Parse.Object.extend("Recipe");
var Ingr = Parse.Object.extend("Ingredient");
recipeQuery= new Parse.Query(Recipe);
recipeQuery.exists("ingredients");
query = new Parse.Query(Ingr);
query.doesNotMatchQuery("recipe",recipeQuery);
query.ascending('name');
query.find({
success: function (data) {
if (data.length > 0) {
$scope.loadingMsg = '';
}
$scope.ingredients = data;
}
});
angular
.module('app.services')
.service('siteService', function($q, ParseService, $timeout) {
var that = this;
this.fetchIngr = function() {
return this.fetchRecipes().then(function(recipes) {
var q = recipes.reduce(function(initial, current) {
initial.push(that.fetchIngredient(current));
return initial;
}, []);
return $q.all(q);
});
};
this.fetchRecipes = function() {
var defer = $q.defer();
var Recipe = Parse.Object.extend("Recipe");
recipeQuery = new Parse.Query(Recipe);
recipeQuery.ascending('name');
recipeQuery.find({
success: function(data) {
console.log('data', data)
defer.resolve(data);
},
error: function(error) {
defer.reject(error);
}
});
return defer.promise;
};
this.fetchIngredient = function(recipe) {
var defer = $q.defer();
recipe.relation('ingredients').query().find({
success: function(res) {
defer.resolve(res);
},
error: function(error) {
defer.reject(error);
}
});
return defer.promise;
};
})
Usage:
siteService.fetchIngr().then(function(all){
console.log('flatten all ingr for used recipes',[].concat.apply([], all));
});
in the fetchIngr function you will receive array of all ingredients that are used in the Recipe. then you have to the diff between two arrays to find not used ingredients. To do the subtract you should fetch all ingredients and to make subtraction between two arrays (one used ingrdients for recipes and the one with all ingredients). see here the post : JavaScript array difference
if you have questions feel free to ask me.

Categories

Resources