MongoDB: Understanding cursors and there usage - mongodb

I am Just a starter to mongo DB. While going through mongoDB documents, I found out few statements, The statements are given below
var store_test2 = db.test2.find();
var store_test2_1= store_test2.hasNext() ? store_test2.next(): null;
print(store_test2_1.friends);
I've few question from the above code.
What is ? in the above code and why my code wont run without specifying it?
The store_test2 stores the documents that is returned from collection test2.
Test2 collection has many documents. The documents present inside the collection have
a key or attribute called friends. I want to print the values of friends for of all
the documents.
I am able to achieve the requirement by using functions .
But How do I achieve the same by using similar code given above?
for example I have 5 documents each having attribute friends as 34,344,54,32,444.
My output should look like
34
344
54
32
444
The above code would give me output for only one document's attribute "friends" i.e 34.
Can anybody please suggest me some links in which I can find information on
mongoDB background jobs.
How read and write happens.
Cluster behavior.
Primary and secondary node behavior .
Whole Architecture of mongoDB.

1.What is ? in the above code
? and : are the conditional operator. It is a shorthand for if...else in assignments. The long form of that line would be:
var store_test2_1;
if (store_test2.hasNext()) {
store_test2_1 = store_test2.next();
} else {
store_test2_1 = null;
}
2. I want to print the values of friends for all of the documents.
A MongoDB cursor works like an iterator. You can use the method .next() to retrieve more documents as long as .hasNext() returns true. You can do this with a while-loop:
while(cursor.hasNext()) {
var document = cursor.next();
print(document.friends);
}
3.Can anybody please suggest me some links
Stackoverflow is straving to become a knowledge base, not a link collection, so please don't ask for links. Ask specific questions and we will try to answer them.
That being said, all these topics are described in the MongoDB manual. When you have specific questions, feel free to ask them as new questions.

Related

Need help querying distinct combinations of nested fields

Desired result
I am trying to query my collection and obtain every unique combination of a batch and entry code. I don't care about anything other than these fields, the parent objects do not matter to me.
What I have tried
I tried running:
db.accountant_ledgers.aggregate( [ {"$group": { "_id": { entryCode: "$actions.entry.entryCode", batchCode: "$actions.entry.batchCode" } } } ]);
Problem
I get unexpected results when I run that query. I'm looking for a list of every unique combination of batch and entry codes, but instead I get a list of arrays? Perhaps these are the results I'm looking for, but I have no idea how to read them if they are.
Theory
I think perhaps this could have to do with the fact that these fields are nested. Each object has several actions, each action has several entries. I believe that the result from that query is just the aggregated entry and batch codes found in each object. I don't know how long the list of results is, but I'd guess it's the same number as the total number of objects in my collection (~90 million).
EDIT: I found out that there are only 182 results from my query, which is clearly significantly smaller than 90 million. My new theory is that it has found all unique objects, with the criteria for "uniqueness" being the list of the batch and entry codes that appear in their actions, which makes sense. There should be a lot of repetition in the collection.
Question
How can I achieve the result I'm looking for? I'm expecting something like:
FEE, MG
EXN, WT
ACH, 9C
...etc
Notes
I apologize if this is a bad question, I'm not sure how else to frame it. Let me know if I can improve my question at all.
Picture below shows the results of the query.
EDIT FOR ADDITIONAL INFORMATION
I can't share any sample documents, but the general structure of the data is shown (crudely) in the below image. Each Entity has several Actions, each Action has one Entry and each Entry has one Batch code and one Entry code.
List item
You are getting a list of documents (each is a map or a hash), not a list of arrays.
The GUI you are using is trying to show you the contents of each document on the top level which is maybe what is confusing.
If you run the query in mongo shell you should see a list of documents.
It looks like your inputs are documents where entry code and batch code are arrays, if so:
Edit your question to include sample documents you are querying as text
You could use $unwind to flatten those arrays before using $group.

Basic MongoDb Retrieval

I have two "documents" that I inserted into my MongoDB database.
questionsList.insert({question: "When was the War of 1812", answer: "1812", answers: ["1811", "1812", "1813", "1814"]})
questionsList.insert({question: "What year did the US land on the moon?", answer: "1969", answers: ["1969", "1970", "1971", "1972"]})
I simply want to access the answer value from the second document. I have been reading the documentation and it doesn't seem to work. I can retrieve the answer value from the first document without issue: var str = questionsList.findOne({}, {question: 1}).answer; I presume that since I am using findOne I can't find any other matches. The problem is that I can't seem to pull up the second document and its corresponding answer. I have tried many different ways:
questionList.find({}, {answer: 1})
questionList.find({answer: 1})
questionList.find({}).answer
My ultimate goal is to compare this answer with one of the click one answers from choices What am I missing?
If I understood your scenario correctly, you are trying to retrieve a document based on the document index (Which is not the right thing to do, since MongoDB does not store documents in specific order).
The reason why findOne works is, because it just returns the first document in your collection.
What I believe you should do instead is retrieve the answer based on the question. Something like:
db.questionsList.find({question:"What year did the US land on the moon?"},{answer:1})
Update:
In the case of meteor.js
questionsList.find({question:"What year did the US land on the moon?"}).fetch()[0].answer
The reason whey we need to give [0] is fetch() returns an array of objects. (Since there can be multiple documents with same key)
The final step is:
questionsList.find({"question": "You are human"}, {"answer": 1}).fetch()[0].answer
We are treating it as any other object (i.e. the first within a list of objects and using dot-notation)

MongoDB Describe Collection

I have a user collection ,I want to see schema for this collection with data type and other detail,which I want to use in mongoosJs while making Schema.
I found a way on internet ,but it is not providing me full detail of collections-below is code for same
var users= db.users.findOne();
for (var key in users) { print (key) ; }
Is there any way to find it.
You can modify your code as per lines below:-
var col_list = db.users.findOne();
for (var col in col_list) {print (typeof col) }
There is no such thing as a schema in mongo. Documents can differ greatly from each other.
So there can be one document where field username is String and another document where field username is Integer.
You could extract the 'schema' from collection by iterating over all documents and collecting schematic information from all of them and then merging that information. But as far as I know there is no direct way in mongo itself.
Edit: a little googling landed me at variety.js, which seems to do what you need.

Get a document in MongoDB without specifying collection

MongoDB IDs are unique for a single database cluster. Is it possible to get documents using their IDs, without specifying the collection name?
If yes, how?
If no, why not?
Yes, but not in a scalable way (since you must query each collection). If you have 2 or 3 collections, this might be ok, but... you probably should review your design to figure out why you're doing this. Why are you, by the way?
You get a list of all of the collections in the database.
You loop through them, and query based on _id
Sample shell code:
db.test1.save({});
db.test2.save({});
db.test3.save({});
db.test4.save({});
db.test5.save({});
db.test6.save({});
db.test2.findOne(); // gives: { "_id" : ObjectId("4f62635623809b75e6b8853c") }
db.getCollectionNames().forEach(function(collName) {
var doc = db.getCollection(collName).findOne({"_id" : ObjectId("4f62635623809b75e6b8853c")});
if(doc != null) print(doc._id + " was found in " + collName);
});
gives: 4f62635623809b75e6b8853c was found in test2
ObjectId is designed to be globally unique (worldwide, not just within a single cluster). And it pretty much is.
It includes time, machine id, process id and a random number. However, it does not include database or collection name. Therefore, it is impossible to fetch a document using only the id. You have to provide database and collection names as well.

How do I describe a collection in Mongo?

So this is Day 3 of learning Mongo Db. I'm coming from the MySql universe...
A lot of times when I need to write a query for a MySql table I'm unfamiliar with, I would use the "desc" command - basically telling me what fields I should include in my query.
How would I do that for a Mongo db? I know, I know...I'm searching for a schema in a schema-less database. =) But how else would users know what fields to use in their queries?
Am I going at this the wrong way? Obviously I'm trying to use a MySql way of doing things in a Mongo db. What's the Mongo way?
Type the below query in editor / mongoshell
var col_list= db.emp.findOne();
for (var col in col_list) { print (col) ; }
output will give you name of columns in collection :
_id
name
salary
There is no good answer here. Because there is no schema, you can't 'describe' the collection. In many (most?) MongoDb applications, however, the schema is defined by the structure of the object hierarchy used in the writing application (java or c# or whatever), so you may be able to reflect over the object library to get that information. Otherwise there is a bit of trial and error.
This is my day 30 or something like that of playing around with MongoDB. Unfortunately, we have switched back to MySQL after working with MongoDB because of my company's current infrastructure issues. But having implemented the same model on both MongoDB and MySQL, I can clearly see the difference now.
Of course, there is a schema involved when dealing with schema-less databases like MongoDB, but the schema is dictated by the application, not the database. The database will shove in whatever it is given. As long as you know that admins are not secretly logging into Mongo and making changes, and all access to the database is controller through some wrapper, the only place you should look at for the schema is your model classes. For instance, in our Rails application, these are two of the models we have in Mongo,
class Consumer
include MongoMapper::Document
key :name, String
key :phone_number, String
one :address
end
class Address
include MongoMapper::EmbeddedDocument
key :street, String
key :city, String
key :state, String
key :zip, String
key :state, String
key :country, String
end
Now after switching to MySQL, our classes look like this,
class Consumer < ActiveRecord::Base
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :consumer
end
Don't get fooled by the brevity of the classes. In the latter version with MySQL, the fields are being pulled from the database directly. In the former example, the fields are right there in front of our eyes.
With MongoDB, if we had to change a particular model, we simply add, remove, or modify the fields in the class itself and it works right off the bat. We don't have to worry about keeping the database tables/columns in-sync with the class structure. So if you're looking for the schema in MongoDB, look towards your application for answers and not the database.
Essentially I am saying the exactly same thing as #Chris Shain :)
While factually correct, you're all making this too complex. I think the OP just wants to know what his/her data looks like. If that's the case, you can just
db.collectionName.findOne()
This will show one document (aka. record) in the database in a pretty format.
I had this need too, Cavachon. So I created an open source tool called Variety which does exactly this: link
Hopefully you'll find it to be useful. Let me know if you have questions, or any issues using it.
Good luck!
AFAIK, there isn't a way and it is logical for it to be so.
MongoDB being schema-less allows a single collection to have a documents with different fields. So there can't really be a description of a collection, like the description of a table in the relational databases.
Though this is the case, most applications do maintain a schema for their collections and as said by Chris this is enforced by your application.
As such you wouldn't have to worry about first fetching the available keys to make a query. You can just ask MongoDB for any set of keys (i.e the projection part of the query) or query on any set of keys. In both cases if the keys specified exist on a document they are used, otherwise they aren't. You will not get any error.
For instance (On the mongo shell) :
If this is a sample document in your people collection and all documents follow the same schema:
{
name : "My Name"
place : "My Place"
city : "My City"
}
The following are perfectly valid queries :
These two will return the above document :
db.people.find({name : "My Name"})
db.people.find({name : "My Name"}, {name : 1, place :1})
This will not return anything, but will not raise an error either :
db.people.find({first_name : "My Name"})
This will match the above document, but you will have only the default "_id" property on the returned document.
db.people.find({name : "My Name"}, {first_name : 1, location :1})
print('\n--->', Object.getOwnPropertyNames(db.users.findOne())
.toString()
.replace(/,/g, '\n---> ') + '\n');
---> _id
---> firstName
---> lastName
---> email
---> password
---> terms
---> confirmed
---> userAgent
---> createdAt
This is an incomplete solution because it doesn't give you the exact types, but useful for a quick view.
const doc = db.collectionName.findOne();
for (x in doc) {
print(`${x}: ${typeof doc[x]}`)
};
If you're OK with running a Map / Reduce, you can gather all of the possible document fields.
Start with this post.
The only problem here is that you're running a Map / Reduce on which can be resource intensive. Instead, as others have suggested, you'll want to look at the code that writes the actual data.
Just because the database doesn't have a schema doesn't mean that there is no schema. Generally speaking the schema information will be in the code.
I wrote a small mongo shell script that may help you.
https://gist.github.com/hkasera/9386709
Let me know if it helps.
You can use a UI tool mongo compass for mongoDb. This shows all the fields in that collection and also shows the variation of data in it.
If you are using NodeJS and want to get the all the field names using the API request, this code works for me-
let arrayResult = [];
db.findOne().exec(function (err, docs)){
if(err)
//show error
const JSONobj = JSON.parse(JSON.stringify(docs));
for(let key in JSONobj) {
arrayResult.push(key);
}
return callback(null, arrayResult);
}
The arrayResult will give you entire field/ column names
Output-
[
"_id",
"emp_id",
"emp_type",
"emp_status",
"emp_payment"
]
Hope this works for you!
Consider you have collection called people and you want to find the fields and it's data-types. you can use below query
function printSchema(obj) {
for (var key in obj) {
print( key, typeof obj[key]) ;
}
};
var obj = db.people.findOne();
printSchema(obj)
The result of this query will be like below,
you can use Object.keys like in JavaScript
Object.keys(db.movies.findOne())