Changing the MongoDB collection on run time in symfony2 + doctrine - mongodb

I'm using Symfony2 MongoDB + Doctrine and I want to tell doctrine to save my objects in collections with different name from the name of the class that defines the object. Also the name of the new collection should be the id of an object in different collection. For example I have a class called Posts and I want to save them in a collection named after the ID of the user in the original User collection. This means that I need to tell doctrine to save all new posts in a collection named e.g. User555 and I should be able to tell doctrine to create this collection and save there during runtime.
I can see that I can change the name of the collection statically with configuring it in the files like here: Storing a document in a different collection - Mongodb with symfony2
But I need to be able to create collections at runtime.
I will be thankful if someone points me in the right direction!
Cheers.

When you use the ORM you can do
$em->getClassMetadata('\AcmeBundle\Entity\Something')->setTableName('test')
Using the ODM you should be able to do
`$dm->getClassMetadata('\AcmeBundle\Document\Something')->setCollection('test')
I looked through the Doctrine code and it's possible. However note that by doing this you're changing the collection used for that Document for the life of the script, unless you set it back.
I don't know of any reasonable way to do this for just one entity at a time. Probably would be best to wrap the ODM by creating your own persister service.

Related

mongodb schema design - add collection or extend existing one

There's a collection with 100.000 documents. Only 10 of them must have additional property that is not necessary for other documents (e.g. list of departments with only top ones have property 'Location');
As far as I understand both approaches should work just fine, but which one is preferable since using noSql db:
add one more collection with documents that have 2 property: DepartmentId, Location.
add property 'Location' to only selected documents, so others won't have it.
The problem you are facing is well known. You have the same with source code for example.
When you are updating a piece of code, do you save it as User.js, User2.js, User3.js ... ?
Or do you use a versionning system like git and have an unique User.js?
Translating the git analogy to your issue, you should update the current data.
In mongodb you actually have two choice to perform the update.
Update the model in your code, and update every entry in database to match the new model.
Create a new model that will apply to new entries, and still have the old model to handle old formatted data.
use-more-than-one-schema-per-collection-on-mongodb

In a nosql database like MongoDB or Couchbase how to model many to many relationship?

Consider a scenario of an application where I have users and projects and the requirement is users shall be assigned to projects. One user can be assigned to multiple projects. This is a many to many relationship. So what is the best way to model such a requirement.
I will like to discuss few approaches to model such a requirement :
- Embeded data model
In this approach I will embedd the user documents inside projects document.
Advantages : you get all the required data in one API call OR by fetching one single document.
Disadvantages : Data duplicacy which is OK
Real problem is if you update user information for eg user mobile no or name from users screen then this updated information should also be reflected under all embedded user documents. For this some bulk update query should be fired.
But is this the right way ???
- Embedding object references instead of objects (which is normalised)
In this case if we embedd user id's instead of user objects then the problem mentioned above wont be there but then we will have to make multiple network calls to get required data or make a seperate relation kond of document as we do in SQL.
Is this the best way ??
We have a same scenario, so i embed objectId. and for fill data for clients, populate users data in find function.
contract.find({}).populate('user').then(function(){});
There are few hard and fast rules, but usually with many-to-many relationships you would prefer references over embedding. This doesn't mean your data is totally flat/normalized.
For example, you could have a user document with an array of project ids. You could have the reverse for projects.
Think about your queries and how you will structure them. That can give you other hints about how to structure your documents.

How to use ensureIndex with AdvancedDatastore by specifying a collection name?

In morphia you can use #Index annotations to create automated indexes for #Entity classes. I am trying to create these indexes by specifying a collection name but couldn't find a way to do it. Using AdvancedDatastore you can save an Entity into any collection you want, but is it possible to ensure indexes on a specified collection rather than the default collection of the Entity.
advancedDatastore.ensureIndexes(Entity.class); // This will create indexes on the mapped Entities.
I am looking for a way to do the following, but I didn't see any method similar to below one, is there a workaround to achieve this:
advancedDatstore.ensureIndexes("exampleCollection", Entity.class); //create indexes of Entity.class for the exampleCollection.
Yes, you can extend the AdvancedDatastore interface and the DatastoreImpl concrete class to add ensureIndex* methods with the extra argument. We do this in our organization and it works.
There is also a pending pull request to add this feature directly to Morphia here: https://github.com/mongodb/morphia/pull/541. If you are willing to build your own Morphia jar, you can use the patch listed there.

Preventing duplicates in MongoDB using Spring Data (Spring Roo)

I have been trying to get my head wrapped around MongoDB, as it's used by Spring, so I decided to start a little project in Spring Roo.
In my project, I am storing my User Login data to MongoDB. The trouble is that the registration process, which creates a new User object and stores it in the MongoDB, has a tendency to create duplicates despite the fact I have #Unique on the loginId field.
Now, I know part of the problem is that I am thinking about things from a JPA/RDBMS perspective, and MongoDB is not a relational DB and thus has a different set of parameters in which to operate with, but I having trouble finding guidance in anything more than a VERY simple sample code.
First, what Spring/Other annotations are available, and more importantly, commonly used when dealing with MongoDB from a Spring-world? Second, when dealing with documents that need to be "uniqued", how does one typically do this? Do you first search on the unique field to ensure it's not already there first, then do the insert? Third, in JPA-land, I could use the annotations #PrePersist and #PreUpdate to do last-minute data manipulation, like MD5-hashing passwords that have been updated or adding/updating a "Last Modified" date just prior to storing. I know this are JPA-isms, but can I still use those, and if not, is there an alternative for use with Spring Data/MongoDB?
I ended up using the #Id annotation on my Entities, which indicates which field is used as the id field. As long as the field is unique, writting subsequent updates will properly replace the existing entity instead of adding a new one.
I ended up creating additional method to check if there exists a data which have a duplicate value to the one we are entering.
If it exists, i return failure mentioning that there exist duplicate value. Otherwise it saves the newly entered value

Morphia and object graphs

I've yet to use Morphia, but I'm considering it for a current project.
Suppose I have a POJO with a number of #Reference annotations and I ask Morphia to fetch the object graph from the database. If I then make another DAO or DataStore call and ask Morphia to fetch some object that was already instantiated in the first graph, would Morphia return a reference to the already instantiated object or would it create a new instance?
If Morphia returns a new instance of the object each time, does anyone have a recommendation of how to best approach creating a Morphia-backed repository that won't duplicate already-instantiated objects?
As I see it in Morphia, it will re read every reference.
This is one of the problems, why I created Morphium. I integrated a caching layer there, so if you read a reference, this one won't be read again (at least, if you search by ID...)
We use morphia in production and there are two ways to make sure you don't load the references which is something we came across too.
One is to use the lazy loading option when you define the #Reference element in your main class. This of course means that this behavior is 'global' to that object.
The better way to do this is to not define an #Reference using Morphia and instead managing the references yourself. Let me know if you need a code sample.
I've stopped using #Reference too and instead declare something like:
ObjectId itemId
rather than having a field item. This has 2 benefits: (1) it lets me define a getter through a helper getObject(...) method which I have written with object caching and (2) it stores a simple ObjectId in the Mongo object rather than a full DBRef which includes the collection name and thus about twice the data size.