Parse.com: Find all objects belonging to a user with objectId - javascript

I have a Class in parse, say Pictures. Each of these belongs to a user. Reference to this user is stored in the Pictures table/class as a Pointer to the user.
In my cloud code I am trying to get all Pictures belonging to a user, using master key. Following is my code:
Parse.Cloud.define("getPictures", function(request, response) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Pictures");
query.equalTo("user", request.params.user);
query.find({
success: function(results) {
var status = "Found " + results.length + " pictures for userId " + request.params.user;
response.success(status);
},
error: function() {
status = "No pictures exist for userId " + request.params.user;
response.error(status);
}
});
});
This code outputs that there are 0 pictures for a certain user with id 'xyz' for example. However, I can see that the user has a lot of pictures stored.
I have also verified that the problem is not with using master key, as I see in the console log that the code is being executed as master. Moreover, if I query for a picture by objectId, it does come out in the results, which means ACL is not the problem here.
I think I have to use relations/joining here, but I am not sure how to do that.

Pointers are stored as objects in Parse database, so if you try to compare a string to an object with query.equalTo() function, nothing will be found. This is how pointers are stored:
{
__type: 'Pointer',
className: '_User',
objectId: user-object-id
}
If you are querying a class with pointers and want your result comes with the whole object nested, you should set this in your query:
var query = new Parse.Query('Pictures');
query.include('user');
In my queries when I want to search by a pointer column, I compare my user object with the nested user object.
var user = new Parse.User();
// Set your id to desired user object id
user.id = your-user-id;
var query = new Parse.Query('Pictures');
// This include will make your query resut comes with the full object
// instead of just a pointer
query.include('user');
// Now you'll compare your local object to database objects
query.equalTo('user', user);
query.find({
success: function(userPicture) {
response.success(userPicture);
}
});
Anyway, seems that if you have many pictures related to an user, you probably are searching for parse relations instead of pointers: https://www.parse.com/docs/relations_guide

If you write a query to retrieve a parent object and a child object to which you have pointer, but no read access as per ACL, then the query may return only parent object and child will be null because the ACL wont let you read it.

There may be a problem with your params. If "user" is a pointer, then 'request.params.user' is incorrect, because PFObjects may not be sent as params. If "user" is a pointer, use 'request.user'. If request.params.user is a string of the userId, you could use the Id to reconstruct a PFObject shell before the query as was suggested by Murilo already, but deleting the "user" param and using request.user would shorten your code and not duplicate any values. Murilo's solution is also beneficial because you could pass a userId other than the current user's Id.

Related

How can I access a specific attribute of a specific document in a mongoDB collection?

To summarize, I am working with 2 collections - 'usercollection' and 'groupcollection' and I would like to associate users with groups. I don't want to have 2 copies of all the user documents so I have a unique ID attribute for each user that I want to use to associate specific users with specific groups. This is all running on a localhost webserver so I'm getting the input from an html page with a form in it where you enter 'username' and 'groupname'. I tried using the .distinct() function with query as 'username' and the target field/attribute as 'uid'.
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var userName = req.body.username;
// Set query and options for searching usercollection
var query = {"username" : userName};
const fieldName = "uid";
// Set our collections
var users = db.get('usercollection');
// Get UID corresponding to username
var uidToAdd = users.distinct(fieldName, query);
This is what I attempted (with some other lines that aren't relevant taken out) but it just returned a null object so I'm at a bit of a loss. Also, I'm still a beginner with nodejs/javascript/mongoDB so the more informative the answer the better! When I do the same code in the mongo shell I can get the actual value of the 'uid' attribute so I really don't know what's going wrong
I am not sure I am following you. But if I understood correctly, if you want to make a relationship between 'usercollection' and 'groupcolletion', you can simply create those 2 collections and each user in 'usercollection' should have a field with 'groupid' as a reference. In this way, you can access 'groupcollection' easily.
Here is an example with using mongoose.
In User model
...
groupId: {
type: mongoose.Schema.Types.ObjectID
ref: "Group"
}
...
Later you can also use 'populate' to fetch 'Group' information.
...
let data = await User.findById(id).populate('groupId');
...

Stored procedure azure Cosmos DB returns empty collection

I tried to create a stored procedure using the sample sp creation code from Azure docs, but i couldn't fetch the collection details. It always returns null.
Stored Procedure
// SAMPLE STORED PROCEDURE
function sample(prefix) {
var collection = getContext().getCollection();
console.log(JSON.stringify(collection));
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r',
function (err, feed, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
var response = getContext().getResponse();
var body = { prefix: prefix, feed: feed[0] };
response.setBody(JSON.stringify(body));
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
The console shows only this.
the results shows no doc found because of not getting collection.I have passed the partition key at time of execution via explorer.
I had a similar issue. I think the Azure portal doesn't execute stored procedures properly when the partition key is not a string.
In my case I had a partitionKey that is a number. When I executed the stored procedure via the portal I always got an empty resultSet, even though I had documents in my database. When I changed the structure a little, and made my partitionKey a string, the stored procedure worked fine.
Did you create the ToDoList Database with the Items Collection? Yo can do this from the Quick start blade in the Azure portal.
And then create an SP to run against that collection. There is no partition key required, so no additional params are required (leave blank).
The Collection is created without any documents. You may choose to add documents via the Query Explorer blade or via the sample ToDoList App that is available via the Quick start blade.
You are debugging in a wrong way.
It is perfectly fine to see "{\"spatial\":{}}" in your console log, even if the collection has items. Why? well because that is a property of that object.
So regarding what you said:
the results shows no doc found because of not getting collection
is false. I have the same console log text, but I have items in my collection.
I have 2 scenarios for why your stored procedure return no items:
I had the same issue trying on azure portal UI(in browser) and for my surprise I had to insert an item without the KEY in order that my stored procedure to see it.
On code you specify the partition as a string ie. new PartitionKey("/UserId") instead of your object ie. new PartitionKey(stock.UserId)

JavaScript (Discord) Is there a way for my bot to store values and then repeat?

I have my current Discord Bot project using JavaScript however i cannot find a way to store the value itself when done through a command such as !setname ___ hoping for a response of that being repeated back when I use !myname.
I know how to do it by storing it temporarily through:
bot.on('message', function (user, userID, channelID, message, evt) {
if(message == "!myname") {
bot.sendMessage({
to: channelID,
message: 'Your name is ' + user.username;
});
}
}
However i cant figure out how to do it through the ability to call for it whenever you want rather than getting an immediate response. For example setting my name now but being able to have it output when i use the command instead of having command that sets the value then outputs it in an immediate string
Would recommend a simple key-value dictionary style in the current instance.
(Though you could store it to a text-file or database later if you prefer the data to be persistent across different sessions.)
Instance based:
Based on this post on stackoverflow...
You can create a global dictionary at the top var usernameChangeDict = {};
Whenever the user invokes !setname, just do:
usernameChangeDict[user.id] = Their_new_name_here
Fetch it back using usernameChangeDict[user.id], should return null or empty if they did not set their name before.
Persistent data:
Could either store it in a text file on your local computer, or do a database as Zooly mentioned.(Though personally, a database would be an overkill if your bot is not going to be used by a wide range of people.)
Text file
Read from this post, it contains details on how to write onto a text file.
This post talks about reading from a text file.
I would recommend storing it in a JSON format to make your life easier, since JSON.parse exists.
Most likely you would end up storing in a format like this:
{ "23125167744": "someone", "USER_ID": "username" }
Access it by parsedJson["USER_ID"].
SQLite
This tutorial would probably explain how to set your SQLite for javascript better than I do.
Once its all setup, just store the userID and username, you can just do:
SELECT username FROM yourTable WHERE userID = ?;
and
INSERT INTO yourTable (username, userID) VALUES (?, ?);
For inserting and selecting into database respectively.

Parse - limit result of a Query in Cloud Code

Hello is this code in the comment possible with Parse Cloud Code?
Parse.Cloud.beforeFind('Note', function(req) {
var query = req.query;
var user = req.user;
// if a given 'Note' visibility is set to 'Unlisted'
// return only the Notes with 'user' field that the calling _User
});
The documentation only shows how to filter fields that are returned but not exactly remove items from the query result in the Cloud Code.
This can be done through ACL, I know, but the caveat is that if the request is a retrieve function and not query the Note should still return.
Assuming you've saved the user as an object relationship (not a string id). Just add the qualification you need, such as:
query.equalTo("your_user_pointer_col_on_Note", user)

Two equalTo in parse.com javascript [duplicate]

I need to connect 2 queries in Parse.com with an and, my code is:
var queryDeseo1 = new Parse.Query(DeseosModel);
queryDeseo1.equalTo("User", Parse.User.current());
queryDeseo1.equalTo("Deseo", artist);
queryDeseo1.find({...
The result of the .find is all the objects with User = Parse.User.current()) and all the objects with Deseo = artist but I want the objects with the two queries together:
User = Parse.User.current()) and Deseo = artist
You've actually got it setup correctly to do an AND query. The problem (assuming that your data structure is setup properly) is that your User field is a Pointer to the User table. Therefore, you need to query for a User equal to the pointer, as opposed to a User equal to Parse.User.current() which will return a string. Something like the following:
var userPointer = {
__type: 'Pointer',
className: 'User',
objectId: Parse.User.current().id
}
queryDeseo1.equalTo('User', userPointer);

Categories