Find the collection name from document._id in meteor (mongodb) - mongodb

From the looks of the syntax for handling mongodb related things in meteor it seems that you always need to know the collection's name to update, insert, remove or anything to the document.
What I am wondering is if it's possible to get the collection's name from the _id field of a document in meteor.
Meaning if you have a document with the _id equal to TNTco3bHzoSFMXKJT. Now knowing the _id of the document you want to find which collection the document is located in. Is this possible through meteor's implementation of mongodb or vanilla mongodb?

As taken from the official docs:
idGeneration String
The method of generating the _id fields of new documents in this collection. Possible values:
'STRING': random strings
'MONGO': random Meteor.Collection.ObjectID values
The default id generation technique is 'STRING'.
Your best option would be to insert records within a pseudo transaction where the second step is to take the id and collection name to feed it into a reference collection. Then, you can do your lookups from that.
It would be pretty costly, though to construct your find's but might be a pattern worthwhile exploring if you are building an app where your users will be creating arbitrary data patterns.

You could accomplish this by doing a findOne on all of the collections:
var collectionById = function(id) {
return _.find(_.keys(this), function(name) {
if (this[name] instanceof Meteor.Collection) {
if (this[name].findOne(id)) {
return true;
}
}
});
};
I tested this on both the client and the server and it seemed to work when run in the global context.

Related

Meteor React - Why is findOne on a single document not found in miniMongo when it does exist?

This is such a weird problem. I think it has to do with how I am querying the document. It seems like the Meteor API has changed to query documents but the docs on the website are the same.
Here is a document in the database:
meteor:PRIMARY> db.studies.findOne()
{ "_id" : ObjectId("56c12e6537014a66b16771e7"), "name" : "Study 1" }
I have subscribed to get all documents and here is what I am trying in the console to get the documents.
var study = Studies.findOne() // This works.
It returns:
_id: MongoID.ObjectID
_str: "56c12e6537014a66b16771e7"
name: 'Study 1'
I just started a new Meteor project with React. I see that my collection is returning _id: MongoId.ObjectId
This is different, I have been using Meteor for awhile with Blaze and I can't remember it returning MongoID.ObjectID instead of just the string
But now if I try and find just that one document, it does not work.
var study = Studies.findOne("56c12e6537014a66b16771e7");
or
var study = Studies.findOne({_id: "56c12e6537014a66b16771e7"});
I am positive I am queuing for the right _id field. I have double checked the ID. Why does trying to find this one document not work?
Please let me know how I can query for a document. Has something changed with Meteor? The documentation still says you can search by id string.
You need to explicitly cast object id string to an ObjectID
var study = Studies.findOne({_id: new Meteor.Collection.ObjectID("56c12e6537014a66b16771e7")});
#Jaco has the correct answer, but I wanted to answer here to clarify what the higher level issue was.
The reason why my find query was not following syntax in Meteor docs is because I inserted the document into MongoDB directly, instead of through the Meteor API.
If you insert the document directly into MongoDB, you have to query the document using the syntax #Jaco mentioned in his answer.
Similar question: Meteor - Find a document from collection via Mongo ObjectId
So instead of changing my query code, I just deleted the document I inserted directly into MongoDB, and inserted a documented using the console in the browser.
Now I can query the document like normal.
So the root of the issue is that if you insert the document directly into MongoDB, you don't get the same type of document as you would if you insert the document using the Meteor API.

Field's datatype of collection in mongodb

How to get field information of a collection in mongodb.
information I am looking for are
field name
data type
You will need to loop over all the documents and figure out what the used names are, and which types each specific field uses. MongoDB does not have a schema, so there is no short cut to fetch this. Be also aware that each field's value can have totally different data types as well—another one of MongoDB's strenghts.
To figure out some statistics, such as field names, the following script can help:
mr = db.runCommand({
"mapreduce" : "things",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "things" + "_keys"
})
Then run distinct on the resulting collection so as to find all the keys:
db[mr.result].distinct("_id");
But there is no way to also include the field types with a Map/Reduce job like this.
You can't determine the schema of a collection. Each of the objects of an collection might have a different schema, you should be aware of this.
I made a similar question a few months ago , in the post you can find how to retrieve the schema of an object using the java programing language; However, to the best of my knowledge, the is no way to retrieve the data types other than try to cast the objects (this is the way the BasicBsonObjects do it).
MongoDB supports dynamic schema, and there is no inbuilt feature for schema introspection or analysis as at MongoDB 2.4.
However .. it is possible to infer the schema by inspecting using a Map/Reduce across either a sample of documents or the entire collection.
There are a few open source tools which package this approach up in a helpful interface, for example:
Schema.js - extends the mongo shell with collection.schema() prototypes
Variety - runs as a standalone script
I like the approach of schema.js, and include it in my ~/mongorc.js startup file so it is available in my mongo shell sessions.
By default schema.js analyzes up to 50 documents in a collection and returns the results inline. There is a limit option to inspect more (or even all) documents in a collection, and it supports the Map/Reduce out options so results can optionally be saved or merged with an output collection.

Mongo find unique results

What's the easiest way to get all the documents from a collection that are unique based on a single field.
I know I can use db.collections.distrinct to get an array of all the distinct values of a field, but I want to get the first (or really any one) document for every distinct value of one field.
e.g. if the database contained:
{number:1, data:'Test 1'}
{number:1, data:'This is something else'}
{number:2, data:'I'm bad at examples'}
{number:3, data:'I guess there\'s room for one more'}
it would return (based on number being unique:
{number:1, data:'Test 1'}
{number:2, data:'I'm bad at examples'}
{number:3, data:'I guess there\'s room for one more'}
Edit: I should add that the server is running Mongo 2.0.8 so no aggregation and there's more results than group will support.
Update to 2.4 and use aggregation :)
When you really need to stick to the old version of MongoDB due to too much red tape involved, you could use MapReduce.
In MapReduce, the map function transforms each document of the collection into a new document and a distinctive key. The reduce function is used to merge documents with the same distincitve key into one.
Your map function would emit your documents as-is and with the number-field as unique key. It would look like this:
var mapFunction = function(document) {
emit(document.number, document);
}
Your reduce-function receives arrays of documents with the same key, and is supposed to somehow turn them into one document. In this case it would just discard all but the first document with the same key:
var reduceFunction = function(key, documents) {
return documents[0];
}
Unfortunately, MapReduce has some problems. It can't use indexes, so at least two javascript functions are executed for every single document in the collections (it can be limited by pre-excluding some documents with the query-argument to the mapReduce command). When you have a large collection, this can take a while. You also can't fully control how the docments created by MapReduce are formed. They always have two fields, _id with the key and value with the document you returned for the key.
MapReduce is also hard to debug an troubleshoot.
tl;dr: Update to 2.4

Mongo _id for subdocument array

I wish to add an _id as property for objects in a mongo array.
Is this good practice ?
Are there any problems with indexing ?
I wish to add an _id as property for objects in a mongo array.
I assume:
{
g: [
{ _id: ObjectId(), property: '' },
// next
]
}
Type of structure for this question.
Is this good practice ?
Not normally. _ids are unique identifiers for entities. As such if you are looking to add _id within a sub-document object then you might not have normalised your data very well and it could be a sign of a fundamental flaw within your schema design.
Sub-documents are designed to contain repeating data for that document, i.e. the addresses or a user or something.
That being said _id is not always a bad thing to add. Take the example I just stated with addresses. Imagine you were to have a shopping cart system and (for some reason) you didn't replicate the address to the order document then you would use an _id or some other identifier to get that sub-document out.
Also you have to take into consideration linking documents. If that _id describes another document and the properties are custom attributes for that document in relation to that linked document then that's okay too.
Are there any problems with indexing ?
An ObjectId is still quite sizeable so that is something to take into consideration over a smaller, less unique id or not using an _id at all for sub-documents.
For indexes it doesn't really work any different to the standard _id field on the document itself and a unique index across the field should work across the collection (scenario dependant, test your queries).
NB: MongoDB will not add an _id to sub-documents for you.

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.