Prettify MongoDb ObjectId - mongodb

We are developing photo gallery which is storing huge amount of photos. We have choosed MongoDB's GridFS for image storage. Every thing looks fine.
But every time when user has to delete the photo we thought of deleting particular photo based on its "ObjectId", but Sending ObjectId to client side looks ugly because of its length. Deleting based on photo name is not possible because its not unique.
So how do we prettify the ObjectId to send it to client side?

Not sure if this belongs as an answer since it's subjective, but then again, so is the question:
If you want to not involve another field, you can change the encoding of the id. I think base64 looks just fine:
55036ee50202b73c1a021897 -> NTUwMzZlZTUwMjAyYjczYzFhMDIxODk3
Another option is to generate a random string and store it on the document, which gives you a lot of customizability in the appearance. For example, you could do 4 digit codes with only upper-case characters like BUZQ. However, be sure to create a unique index so you don't accidentally create duplicate identifiers.

Related

How to update collection documents efficiently when changing a specific value in Firestore?

I have 2 collections. One of them is named "USERS", and the other one "MATCHES". USERS, can join in the MATCHES, appearing the avatar of the user who has joined in the match. The problem is that when the user changes their avatar image after joining in the match, the match avatar doesn't changed, because the match has the old avatar.
The avatar is saved as Base64 in Firestore, but I will change it to "Storage" in the near future.
I have been trying to set the reference, but that only gives me the path.
If I have to do a Database Api Call for each match which is joined the user, maybe I have to do 20 Api calls updating the matches. It can be a solution, but not the best.
Maybe the solution is in the Google Functions?
I'm out of ideas.
Maybe the solution is in the Google Functions?
Cloud Functions also access Firestore through an SDK, so they can't magically do things that the SDK doesn't allow.
If you're duplicating data and you update one of the duplicates, you'll have to consider updating the others. If they all need to be updated, that indeed requires a separate call for each duplicate.
If you don't want to have to do this, don't store duplicate data.
For more on the strategies for updating duplicated data, see How to write denormalized data in Firebase

couchdb, how to rename an attachment

I'm writing cms like application and I would like my images to be stored as attachments in couchdb.
The problem is in naming the attachments because I don't want my images to be named the same (e.g. /db/doc_id/thumb.jpg)
Ideally attachments names should depend on doc.name field. To make this work I would have to rename attachment each time user changed the name (description|alt) of current photo document.
So my question is: how to change attachment name? or maybe I should go other way in solving my problem?
Szymon,
I'd suggest considering using UUIDs for the document names, and storing the attachment as something "static" like "original", "thumb", "300wide", etc. The name given by the user when they upload the file can be stored as a key, and you can use a MapReduce index to retrieve the image/file using that name later.
If you go that route, though, you'll have to come at the "duplicates" problem a bit differently--as you could easily upload the same image multiple times with the same user-provided name and there would be no conflict.
Depending on what you're building, though, making the user provide a unique name is generally unwise--Flickr (among many others) doesn't, for instance.
If you really do need to make the doc_id == the name given by the user, then it would still be wise to store the attachments under static names, so you don't have to update the attachment name.
Lastly, if you feel you really must change the attachment name (and there are certainly cases where you need to), the simplest way is to GET the attachment from the old location (or with the document), PUT it as the new name, and DELETE the attachment with the old name.
Hope that helps!
Use this command >
curl -v http://localhost:5984/database/DocumentID/OldFileName?rev=RevisionID -X MOVE -H "Destination: NewFileName"

What's the best way to store references to a gridFS file in a document?

I'm using MongoDB to store user profiles, and now I want to use GridFS to store a picture for each profile.
The two ways I'm comparing linking the two documents are:
A) Store a reference to the file ID in the user's image field:
User:
{
"_id": ObjectId('[user_id here]'),
"username": 'myusername',
"image": ObjectId('[file_id here]')
}
B) Store a reference to the user in the file's metadata:
File metadata:
{
"user_id": ObjectId('[user_id here]')
}
I know in a lot of ways it's up to me and dependent on the particulars of the app (it'll be mobile, if that helps), but I'm just wondering if there's any universal benefit to doing it one way or the other?
The answer here really depends on your application's usage pattern. My assumption (feel free to correct me) is that the most likely pattern is something like this:
Look Up User --> Find User --> Display Profile(Fetch Picture)
With this generalized use case, with method A, you find the user document, to display the profile) wich contains the image object ID and you subsequently fetch the file using that ID (2 basic operations and you are done).
Note: the actual fetching of the file from GridFS I am treating as a single logical operation, in reality there are multiple operations involved, but most of the drivers/APIs obscure this anyway.
With method B, you are going to have to find the user document, then do another query to find the relevant user_id in the file metadata collection, then go fetch the file. By my count, that is three operations (an extra find you do not have with method A).
Does that make sense?
Of course, if my assumption is incorrect and your application is (for example) image driven, then your query pattern may come up with a different answer.

MongoDB ObjectId foreign key implementation recommendation

I'm looking for a recommendation on how best to implement MongoDB foreign key ObjectId fields. There seem to be two possible options, either containing the nested _id field or without.
Take a look at the fkUid field below.
{'_id':ObjectId('4ee12488f047051590000000'), 'fkUid':{'_id':ObjectId('4ee12488f047051590000001')} }
OR
{'_id':ObjectId('4ee12488f047051590000000'), 'fkUid':ObjectId('4ee12488f047051590000001')} }
Any recommendations would be much appreciated.
I'm having a hard time coming up with any possible advantages for putting an extra field "layer" in there, so I would personally just store the ObjectId directly in fkUid.
I suggest to use default dbref implementation, that is described here http://www.mongodb.org/display/DOCS/Database+References and is compatible with most of specific language drivers.
If your question is about the naming of the field (what you have in the title), usually the convention is to name it after the object to which it refers.
The both ways that you have mentioned are one of the same meaning. But they have different kind of usages.
Storing fkUid like 'fkUid':{'_id':ObjectId('4ee12488f047051590000001')} an object has it's own pros. Let me give an example, Suppose there is a website where users can post images and view images posted by other users as well. But when showing the image the website also shows the name/username of the user. By using this way you also can store the details like 'fkUid':{'_id':ObjectId('4ee12488f047051590000001'), username: 'SOME_X'}. When you are getting details from the db you don't have to send a request again to get the username for the specific _id.
Where as in the second way 'fkUid':ObjectId('4ee12488f047051590000001')} } you have to send another request to the server only for getting the name/username and nothing else is useful from the same object.

Is it ok to turn the mongo ObjectId into a string and use it for URLs?

document/show?id=4cf8ce8a8aad6957ff00005b
Generally I think you should be cautious to expose internals (such as DB ids) to the client. The URL can easily be manipulated and the user has possibly access to objects you don't want him to have.
For MongoDB in special, the object ID might even reveal some additional internals (see here), i.e. they aren't completely random. That might be an issue too.
Besides that, I think there's no reason not to use the id.
I generally agree with #MartinStettner's reply. I wanted to add a few points, mostly elaborating what he said. Yes, a small amount of information is decodeable from the ObjectId. This is trivially accessible if someone recognizes this as a MongoDB ObjectID. The two downsides are:
It might allow someone to guess a different valid ObjectId, and request that object.
It might reveal info about the record (such as its creation date) or the server that you didn't want someone to have.
The "right" fix for the first item is to implement some sort of real access control: 1) a user has to login with a username and password, 2) the object is associated with that username, 3) the app only serves objects to a user that are associated with that username.
MongoDB doesn't do that itself; you'll have to rely on other means. Perhaps your web-app framework, and/or some ad-hoc access control list (which itself could be in MongoDB).
But here is a "quick fix" that mostly solves both problems: create some other "id" for the record, based on a large, high-quality random number.
How large does "large" need to be? A 128-bit random number has 3.4 * 10^38 possible values. So if you have 10,000,000 objects in your database, someone guessing a valid value is a vanishingly small probability: 1 in 3.4 * 10^31. Not good enough? Use a 256-bit random number... or higher!
How to represent this number in the document? You could use a string (encoding the number as hex or base64), or MongoDB's binary type. (Consult your driver's API docs to figure out how to created a binary object as part of a document.)
While you could add a new field to your document to hold this, then you'd probably also want an index. So the document size is bigger, and you spend more memory on that index. Here's what you might not have though of: simply USE that "truly random id" as your documents "_id" field. Thus the per-document size is only a little higher, and you use the index that you [probably] had there anyways.
I can set both the 128 character session string and other collection document object ids as cookies and when user visits do a asynchronous fetch where I fetch the session, user and account all at once. Instead of fetching the session first and then after fetching user, account. If the session document is valid ill share the user and account documents.
If I do this I'll have to make every single request for a user and account document require the session 128 character session cookie to be fetched too thus making exposing the user and account object id safer. It means if anyone is guessing a user ID or account ID, they also have to guess the 128 string to get any answers from the system.
Another security measure you could do is wrap the id is some salt which you only know the positioning such as
XXX4cf8ce8XXXXa8aad6957fXXXXXXXf00005bXXXX
Now you know exactly how to slice that up to get the ID.