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);
Related
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');
...
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)
I am using the module Mongoose for MongoDB. Everytime the user submits data to my node server, it is processed something like this:
var personSchema = mongoose.Schema({ //a new schema
properties: {}, //dynamic properties
keys: [],
houses:[],
family:[]
}, {strict: false});
var NewPerson = mongoose.model('people', personSchema);//
var personObject = {properties: {
keys: ['data that was pushed previously'];
houses: ['data that was pushed previously'];
family: ['data that was pushed previously'];
}}
var person = NewPerson(personObject, false);
person.save(function(err){
if(err){
console.log('database error');
throw err;
}
console.log('cropped document saved.');
});
Now until this point, all is well; problem is, that in the future my users would want to make edits/add new data such as new houses/family etc, how do I do it?
I mean, I already coded a form submission which sends their mongodb id, with that id I want to access the document they saved inside my people collection(I know how to access a document using the function findOne), and then push their new form data to keys, houses, family arrays and finally save it in the database.
Thank you for your time.
or you can just use update() method,this approach can modify the data in the mongodb, you do not need find it, change it and save it.
I'm having some trouble querying a document by values matching inside the document after population by mongoose.
My schemas are something like this:
var EmailSchema = new mongoose.Schema({
type: String
});
var UserSchema = new mongoose.Schema({
name: String,
email: [{type:Schema.Types.ObjectId, ref:'Email'}]
});
I would like to have all users which have a email with the type = "Gmail" for example.
The following query returns empty results:
Users.find({'email.type':'Gmail').populate('email').exec( function(err, users)
{
res.json(users);
});
I have had to resort to filtering the results in JS like this:
users = users.filter(function(user)
{
for (var index = 0; index < user.email.length; index++) {
var email = user.email[index];
if(email.type === "Gmail")
{
return true;
}
}
return false;
});
Is there any way to query something like this straight from mongoose?
#Jason Cust explained it pretty well already - in this situation often the best solution is to alter the schema to prevent querying Users by properties of documents stored in separate collection.
Here's the best solution I can think of that will not force you to do that, though (because you said in the comment that you can't).
Users.find().populate({
path: 'email',
match: {
type: 'Gmail'
}
}).exec(function(err, users) {
users = users.filter(function(user) {
return user.email; // return only users with email matching 'type: "Gmail"' query
});
});
What we're doing here is populating only emails matching additional query (match option in .populate() call) - otherwise email field in Users documents will be set to null.
All that's left is .filter on returned users array, like in your original question - only with much simpler, very generic check. As you can see - either the email is there or it isn't.
Mongoose's populate function doesn't execute directly in Mongo. Instead after the initial find query returns a set a documents, populate will create an array of individual find queries on the referenced collection to execute and then merge the results back into the original documents. So essentially your find query is attempting to use a property of the referenced document (which hasn't been fetched yet and therefore is undefined) to filter the original result set.
In this use case it seems more appropriate to store emails as a subdocument array rather than a separate collection to achieve what you want to do. Also, as a general document store design pattern this is one of the use cases that makes sense to store an array as a subdocument: limited size and very few modifications.
Updating your schema to:
var EmailSchema = new mongoose.Schema({
type: String
});
var UserSchema = new mongoose.Schema({
name: String,
email: [EmailSchema]
});
Then the following query should work:
Users.find({'email.type':'Gmail').exec(function(err, users) {
res.json(users);
});
I couldn't find any other solution other than using Aggregate. It will be more troublesome, but we will use Lookup.
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
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.