MongoDB mass update inserting data from one document to another one - mongodb

I'm still learning about MongoDB and I would like to know if someone could help me with the situation I'm facing.
I'm taking over a DB structure that has been created like a relational DB abd I would like to embed a full document (instead of a reference only to the document) into all my documents.
Let me try to explain the best I can:
I have an activity table that references a user using its userID
activity : {
"user_id" : ObjectId("5324a18d3061650002030000")
}
user_id is the primary id of another document called user.
user:
{
"_id" : ObjectId("5324a18d3061650002030000"),
"active" : true,
"birth_date" : ISODate("1980-03-25T00:00:00.000Z")
}
What I would like to do is to insert my user into my activity document:
activity : {
"user_id" : ObjectId("5324a18d3061650002030000")
user:
{
"_id" : ObjectId("5324a18d3061650002030000"),
"active" : true,
"birth_date" : ISODate("1980-03-25T00:00:00.000Z")
}
}
I would like to do that for all my activity documents (knowing that they all reference different users of course), what would be the best way to do that please?
Thanks a lot guys !!!

It should be simpler like this:
db.users.find().forEach(function(doc) {
db.activity.update({user_id: doc._id}, {$set:{user:doc}});
});

Related

MongoDb Schema Structure

I have a collection named 'Category' with this structure:
{
"CategoryID" : 1,
"ParentID" : 0,
"Name" : "Sample Cat"
}
And another collection which will be using this category
{
"DocumentID" : 1,
"CategoryID" : 1,
"DocumentName" : "Doc XPXSAX"
}
The problem with this design is that when is that I cannot use it to make a live search which will show me the document as
Doc XPXSAX found in Sample Cat"(along with category name without using join)
Also I cannot embed the documents inside the Category collection (as an array in one of the fields) as I am expecting the number of documents to go up to 50k.
What alternate schema design will enable me to incorporate an efficient search functionality without using hacks imitating joins ?
Thanks.
If you dislike an application-level join, why not embed the categories inside the document documents?
{
"DocumentID" : 1,
"category" : {
"ID" : 1,
"Name" : "Sample Cat",
"ParentID" : 0
},
"DocumentName" : "Doc XPXSAX"
}
Keep the category information you need for display in the document document. Information you need more rarely can live in the category document and be found with a second query or application-level join.

MongoDB writing a correct query

I am new to MongoDB and Im trying to write a query to extract data from a collection I created but I am stuck in trying to do so. Any help would be greatly appreciated.
I want to get all the fields except _id for all movies that are NOT based on things
How could I do this in a MongoDB query? I've read and looked up many things trying to learn about Mongo but so far I haven't gotten anything. Thank you very much in advance.
This is my collection:
{ "_id" : ObjectId("5363738hhhe2282828282w"), "coll" : "PageMaster" }
{ "_id" : ObjectId("0000222211223333sssswq2"), "coll" : "Honey1", "Jink" : { "head" : "Jink1"} }
{ "_id" : ObjectId("5hjkwwowwj7373365252wwww"), "coll" : "Rodger", "things" : { "head": "Honey"} }
Just check for the records where the key BOOK does not exist. Those are the records that we want. And exclude the _id field in the projection parameter.
db.MOVI.find({"BOOK":{$exists:false}},{"_id":0})
EDIT:
For using printjson to print the cursor contents:
var myCursor = db.MOVI.find({"BOOK":{$exists:false}},{"_id":0});
myCursor.forEach(function(doc)
{
printjson(doc);
})

Mongodb - ensureindex for record

Is it possible to use ensureindex within records and not for whole collection.
Eg: My database structure is
{ "_id" : "com.android.hello",
"rating" : [
[ { "user" : "BBFE7F461E10BEE10A92784EFDB", "value" : "4" } ],
[ { "user" : "BBFE7F461E10BEE10A92784EFDB", "value" : "4" } ]
]
}
It is a rating system and i don't want the user to rate multiple times on the same application (com.android.hello). If i use ensureindex on the user field then user is able to vote only on one application. When i try to vote on a different application altogether (com.android.hi) it says duplicate key.
No, you can not do this. Uniqueness is only enforced on a per document level. You will need to redesign your schema for the above to work. For example to:
{
"_id" : "com.android.hello",
"rating": {
"user" : "BBFE7F461E10BEE10A92784EFDB",
"value" : "4"
}
}
And then just store multiple...
(I realize you didn't provide the full document though)
ensureIndex
creates indexes , which is applied to whole collection. In case you want only for few records , you may have to keep two collections and apply ensureIndex on one of the collection.
As #Derick said, no however it is possible to make sure they can only vote once atomically:
var res=db.votes.update(
{_id: 'com.android.hello', 'rating.user': {$nin:['BBFE7F461E10BEE10A92784EFDB']}},
{$push:{rating:{user:'BBFE7F461E10BEE10A92784EFDB',value:4}}},
{upsert:true}
);
if(res['upserted']||res['n']>0){
print('voted');
}else
print('nope');
I was a bit concerned that $push would not work in upsert but I tested this as working.

Update collection based on data in another collection in MongoDB

I have two MongoDB collections. questions:
{
"_id" : "8735574",
"title" : "...",
"owner" : {
"user_id" : 950690
},
}
{
"_id" : "8736808",
"title" : "...",
"owner" : {
"user_id" : 657258
},
}
and users:
{
"_id" : 950690,
"updated" : SomeDate,
...
}
{
"_id" : 657258,
"updated" : SomeDate,
...
}
The entries in users have to be regularily created or updated based on questions. So I would like to get all the user_ids from questions that either do not have an entry in users at all or their entry in users was updated more than e.g. one day ago.
To achieve this, I could read all user_ids from questions and then manually drop all users from the result that do not have to be updated. But this seems to be a bad solution as it reads a lot of unneccessary data. Is there a way to solve this differently? Some kind of collection join would be great but I know that this does not (really) exist in MongoDB. Any suggestions?
PS: Nesting these collections into a single collection is no solution as users has to be referenced from elsewhere as well.
Unfortunately there is no good way of doing this and since you don't have access to the indexes to able to do this client side without reading out all the data and manually manipulating it, it is the only way.
The join from users to questions could be done by querying the users collection and then doing an $in on the questions collection but that's really the only optimisation that can be made.

Retrieving only the relevant part of a stored document

I'm a newbie with MongoDB, and am trying to store user activity performed on a site. My data is currently structured as:
{ "_id" : ObjectId("4decfb0fc7c6ff7ff77d615e"),
"activity" : [
{
"action" : "added",
"item_name" : "iPhone",
"item_id" : 6140,
},
{
"action" : "added",
"item_name" : "iPad",
"item_id" : 7220,
}
],
"name" : "Smith,
"user_id" : 2
}
If I want to retrieve, for example, all the activity concerning item_id 7220, I would use a query like:
db.find( { "activity.item_id" : 7220 } );
However, this seems to return the entire document, including the record for item 6140.
Can anyone suggest how this might be done correctly? I'm not sure if it's a problem with my query, or with the structure of the data itself.
Many thanks.
You have to wait the following dev: https://jira.mongodb.org/browse/SERVER-828
You can use $slice only if you know insertion order and position of your element.
Standard queries on MongoDb always return all document.
(question also available here: MongoDB query to return only embedded document)