Parse - limit result of a Query in Cloud Code - javascript

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)

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)

Firebase get all usernames & user Id starting with user entered character

I am trying to only fetch username and user IDs that only start with the User entered text.
Below is my firebase database:
As you can see the database contains a list of user Ids which contains the username.
For Example: If the user enters M in the search box, Query should
return Mr Jois and it's the corresponding user ID.
I am trying to do this using javascript. Below is my code:
function* searchUsers(action) {
const database = firebase.database();
const ref = database.ref('users');
try {
console.log('about to fetch filters users');
const query = ref.orderByChild('username').startAt(action.searchText);
const snapshot = yield call([query, query.once], 'value');
console.log('done fetching users');
console.log(snapshot);
}
catch(error){
console.log(error);
}
}
But I am not getting the expected results. Can someone please tell me how to query the result to get the expected result?
Firebase Database queries do a prefix match, not a contains. But since you only specify startAt(...) the query matches all users from the ones whose name starts with the prefix, including all names after it. If you only want results that start with the prefix string, you'll want to also use endAt(...):
const query = ref.orderByChild('username').startAt(action.searchText)endA‌t(action.searchText+‌​"\uf8ff");
const snapshot = yield call([query, query.once], 'value');
snapshot.forEach(function(child) {
console.log(child.key, child.val().username);
});
Initially, I was thinking the equalTo() query along with Firebase .indexOn the username.
However, what we really need is a substring like ECMAScript 6's String.prototype.startsWith() method:
.startsWith(inputValue);
So, The only way I see to do it with realtime DB is to get/fetch/.once it then process client side where you have more robust string matching capability. I guess the next question is how to pull/fetch only the username property of each user key.
To query based on the first character, you should get that character and pass it to the startAt() function:
const query = ref.orderByChild('username').startAt(action.searchText.charAt(0));

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

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.

How do I get the same format for a javascript array and django set on the backend?

I have code that, when a user is logged in, selects recipes that apply to him based on the ingredients (items) he has previously identified identified as possessions.
This code gets the id's of the items the user already has:
if request.user.is_authenticated():
user_items = [possession.item for possession in request.user.possession_set.all()]
user_items_ids = [item.id for item in user_items]
uids = set(user_items_ids)
The following code, which already existed, is where I run into problems...
recipes = [(recipe, len(set([item.id for item in recipe.items.all()]) & uids), recipe.votes) for recipe in recipes]
I created another part of the site that allows people who have not yet signed up to just pick a few ingredients. I do this with some jQuery on the front end, then send the results to the backend:
var ingredient_set = [];
$('.temp_ingredient').each(function(index){
ingredient_set[index] = $(this).attr('id').substr(4);
});
$.get('/recipes/discover', { 'ingredients': ingredient_set },
function(){
alert("Success");
});
The problem is when I receive them on the Django side, with this code:
uids = request.GET['ingredients']
I get the following error:
unsupported operand type(s) for &: 'set' and 'unicode'
Basically, I know they aren't in the same format, but I don't know how to get them to be compatible.
You are sending a JavaScript array in the query string of your GET request. Therefore you should use request.GET.getlist. Just using request.GET[key] gives you the last value for that key.
>> request.GET['foo[]']
u'5'
>> request.GET.getlist('foo[]')
[u'1', u'2', u'4', u'5']
Note that the values are unicode, but you probably need them as integers, so be sure to convert them.
uids = request.GET.getlist('foo[]')
uids = set([int(x) for x in uids])
I'm not sure why my key is actually foo[] and not just foo, but as you get no KeyError, request.GET.getlist('ingredients') should work.

Categories