MongoDB query using find - mongodb

I am in the process of learning MongoDB and here is the scenario.
I am trying to find user with id. I wrote the code as
Stmt 1
query = {};
query["_id"] = { $ne: ObjectId(data._id) }
It returns me the user with ID. (I have only one test user as of now. So i am not so clear it returns all the user or only user matching the id). But the logic i made is id should not be equal to.
I changed the code like
Stmt 2
query = {};
query = { "_id": { $ne: ObjectId(data._id) } };
Now this is giving me empty array as there are no users matching the id.
What difference does it make in the query to mongodb and why the query failed.

Related

How to query all documents user has access to in mongodb?

I am trying to figure out how to display all documents user has access to but i am either getting no documents at all or undefined user.docs if person is not logged in.
In Meteor, my user has
docs: {
"xxx1",
"xxx2",
"xxx3"
}
etc (it may be limitless number of ids.
How to query mongo to find all documents that have id = user.docs? (return array of docs).
'If a person is not logged in'? I'm assuming this is server side?
Are you trying to grab 'docs' off of Meteor.user() ?
That only works on the current logged in user.
Server side mongodb query on a user:
Meteor.users.findOne({_id: '<userId string here>'},{fields: {docs: 1}});
Should give you:
{_id: '<userId string here>', docs: {...docs here...}}
Be careful with user data!
EDIT:
If you are trying to get docs that match the doc ids from a user object, you would ideally rearrange your data structure to
docs: ['docId', 'docId'] <---this may be your main problem
Then it would be:
var userDocsIds = Meteor.users.findOne({_id: '<userId string here>'},{fields: {docs: 1}});
var userDocs = Docs.find({_id: {$in: userDocsIds.docs}}).fetch();
Use the $in operator to find _ids in an array:
const docIds = Meteor.users.findOne(id).docs;
const myDocs = Docs.find({_id: {$in: docIds }});
i have tried both and ended up using
docs = getDocsForUser(user); //print array of docs
return docs.find({_id: {$in: docs}})

Mongo db conditional query

being a newbie to mongo, stuck in a conditional query:
I want to perform a search on the basis of 3 criteria, first name, last name and email id:
below query works perfect when all the fields exist:
db.students.find( { $and: [ { first_name: /^Abc$/i }, { last_name: 'Xyz'},{email_id:'gd#he'} ]})
the problem is when I don't give an email id , the query dosen't returns any result as it considers the email id to be null and searches for the combination 'Abc Firtis null',
where as I want the below scenario to be fulfilled:
I have a collection of students:
- FirstName: 1. ABC 2. ABC 3.ABC
- LastName: 1.XYZ 2. XY 3. XZ
- EmailID: 1.abc#xyz 2.Ab#xy 3.Ab#xz
if one enters only the first name in the search it should return all the 3 results
if user enters first name and last name it should return first two results and if the user enters all three details it should return only 1 result.
Any leads would be highly appreciated.
You seem to be talking about "input" data being different for the queries you want to issue and how to contruct the query to ignore fields as criteria for which you have no input.
This is all really about how the input is being collected as to how you handle it, but it all boils down to that you "conditionally build" the query ( which is just a data structure anyway ) rather than statically define a query and somehow ignore null or empty data.
So if you have seperate variables, then you test each value and build the query:
var firstName = "abc",
lastName = "xy,
email = null,
query = {};
if (firstName) {
query.firstName = new RegExp("^"+firstName,"i")
}
if (lastName) {
query.lastName = new RegExp("^"+lastName,"i")
}
if (email) {
query.email = new RegExp("^"+email,"i")
}
db.students.find(query)
This would build a query object that would end up like this based on the inputs:
{ "firstName": /^abc/i, "lastName": /^xy/i }
So since there is no value in email then the condition is not included. The end result is the condition not provided is not even queried for and then you get the relevant matches.
The same approach is basically simplified if you have some structured input to begin with:
var params = {
firstName = "abc",
lastName = "xy"
};
var query = {};
Object.keys(params).forEach(function(key) {
if (params[key])
query[key] = new RegExp("^"+key,"i");
});
db.students.find(query);
And it's the same thing, but since you have all parameter keys in one place then you can iterate them to build the query rather than test individually.
This is generally the case where you have input from something like a web request with parameters that come into req.params or even req.body depending on your method of input. So if you structure your code to accept input into a similar object ( or already have it ) then you use it to build your query.
Also note that all MongoDB query arguments are implicitly an "AND" condition by definition, so there is rarely any need to use $and unless you explicitly have multiple conditions to meet for the same document property. Even then there are generally better syntax alternates.
No Need to give and you can simply try this
find( { first_name: { $regex: '/^Abc$/i' }, last_name:'Xyz',email_id:'gd#he'}

Mongo Shell Querying one collection with the results of another

I have 2 different collections and I am trying to query the first collection and take the output of that as an input to the second collection.
var mycursor = db.item.find({"itemId":NumberLong(123)},{"_id":0})
var outp = "";
while(mycursor.hasNext()){
var rec = mycursor.next()
outp = outp + rec.eventId;
}
This query works fine and returns me a list of eventIds.
I have another collection named users, which has eventId field in it. A eventId can repeat in multiple users. So for each eventId I get in the above query I want to get the list of users too.
My query for the second collection would be something like this :
db.users.find({"eventId":ObjectdId("each eventId from above query")},{"_id":0})
My final result would be a unique list of users.
Whell this should basically work ( to a point that is ):
db.events.find({
"eventId": { "$in": db.item.find({
"itemId":NumberLong(123)
}).map(function(doc) { return doc.eventId }) }
})
Or even a bit better:
db.events.find({
"eventId": { "$in": db.item.distinct("eventId",{
"itemId":NumberLong(123) }) }
})
The reason is that "inner query" is evaluated before the outer query is sent. So you get an array of arguments for use with $in.
That is basically the same as doing the following, which translates better outside of the shell:
var events = db.item.distinct("eventId",{ "itemId":NumberLong(123) });
db.events.find({ "eventId": { "$in": events } })
If the results are "too large" however, then your best approach is to loop the initial results as you have done already and build up an array of arguments. Once at a certain size then do the same $in query several times in "pages" to get the results.
But looking for "ditinct" eventId via .distinct() or .aggregate() will help.

Test a parameter inside a mongodb query

I want to avoid to write conditional statements to check parameters before query my database
so that i don't have to write multiple times the similar query but i have to write one single query.
So my first query is
db.results.find( { travel_class : "first" } })
and returns several documents
my second query is
var travel_class_filter = "all";
db.results.find( {'$and' : [ { travel_class_filter : "all"} , { travel_class : "first" } ]})
and returns 0 document instead of the same number of documents of the second query
Do you know why?
You can't test parameters as part of your query, but you can do this by building up your query object programmatically:
var query = {};
if (travel_class_filter != 'all') {
query.travel_class = travel_class_filter;
}
db.results.find(query);

Chats.findOne(id) returns nothing, but db.chats.findOne(ObjectId(id)) does

In my meteor app, I want to publish a chatmate according to the chat object's members: basically there are two members, the one that is not the current user is the one I want to publish. Here's the code. (members is a list which always contains two different user ids)
Meteor.publish('chatmate', function(chat_id) {
var chat = Chats.findOne({_id:chat_id, members: this.userId});
var chatmate = undefined; // just in case... didn't know any better
if (chat) {
for (var i = 0; i < 2; i++) {
if (chat.members[i] !== this.userId)
chatmate = Meteor.users.find(chat.members[i], {fields: {'profile.name': 1}});
}
}
return chatmate;
});
(PS: yes, my publication is in the server folder)
My problem is: my first line of code returns undefined. But if I go on mongo and type db.chats.findOne(ObjectId('<mychatsid>')), I do get my record in the output, along with its members. Problem is, it seems I cannot use this useful ObjectId() method in Meteor!
What am I doing wrong here?
Did you insert these items directly into the mongo shell, or else mongorestore them from another database? By default, Meteor uses strings for _ids (although this can be changed by settings the idGeneration option to "MONGO" when the Collection is declared, as discussed here), whilst stand-alone MongoDB uses ObjectIds, which is what you've got here.
To cut a long story short though, you need to create a new ObjectID object and search based on that if this is the format your _ids are in:
Chats.findOne({ _id: new Meteor.Collection.ObjectID(chat_id), members: this.userId });