Use the same _Id in two models with backbone and mongodb - mongodb

I have two models 'User' and 'point'.
i need when i create a user, with an id like 2juifdsf7tdf65sd67, the same id go to 'point' model.
An ID for the two models sometime.
Its possible?
how to do this in an alternative method?
Update:
when i create the 'User', i need him to get an 'point', the model 'point' get the same id of the user, all in a html view page. but when a create a new user and a point, the id is different, is not the same.

If you put User and Point in 2 different collection you can use same id for those and of couse you should set _id manually
db.User.insert(
{
_id : 100,
...
})
db.Point.insert(
{
_id : 100,
...
})
_id could be number, string and ...
But I think the better solution for u is using reference id
db.User.insert(
{
_id : 100,
point_Id: 13588,
...
})
db.Point.insert(
{
_id : 13588,
...
})

Related

MongoDB - how to only update field if field does not exist

How can I update a mongo document with the following requirements:
Find a document by email property:
If the document exists:
If both retrieved and new document have property A, keep property A (the retrieved one).
If retrieved document property A is null or undefined or doesn't exist, update using property A of the new object.
If the document doesn't exist
Insert the new document.
The findOneAndUpdate seems not to convey the both 3 of the requirements. Thanks.
My recommendation is to go the following path:
db.getCollection('<some-collection>').update(
{ email: 'someguy#email.com' },
{
$set: {
name: "some guy",
username: someguy,
tel: '1234'
}
},
{ upsert: true }
);
Check upsert documentation:
https://docs.mongodb.com/manual/reference/method/db.collection.update/#upsert-option
Lets go through your requirements now:
3. If the document doesn't exist, insert the new document.
Yes, it will insert new document to collection if it doesnt find the document by email. Resulting document will be combination of find condition + $set + autogenerated _id, so it will look something like this:
{
_id: ObjectId(...)
email: 'someguy#email.com'
name: "some guy",
username: someguy,
tel: '1234'
}
2. If retrieved document property A is null or undefined or doesn't exist, update using property A of the new object.
All properties provided in $set will unconditionally be persisted in the database, which also covers your requirement of updating null/undefined values
3. If both retrieved and new document have property A, keep property A (the retrieved one).
If both newly provided A and database A are the same, we dont have a problem.
If As are different, dont you want to store the new A value?
If you are afraid of nulls/undefined values, you can omit them before providing object to $set.
What is the use-case for you not wanting to update database property with newly provided value?
One use-case i can see is that you want to pass createdAt in case you are creating new record, but dont want to update that value for existing records.
If thats the case, and you know those properties in advance, you can use $setOnInsert update operator. https://docs.mongodb.com/manual/reference/operator/update/#id1
So your update query can look like this:
db.getCollection('<some-collection>').update(
{ email: 'someguy#email.com' },
{
$set: {
name: "some guy",
username: someguy,
tel: '1234'
},
$setOnInsert: {
createdAt: new Date(),
updatedAt: new Date()
}
},
{ upsert: true }
);
I hope this helps!
You need not retrieve the document for updating the property A. You can use the update API of mongo to do so. Please find the psuedo code below:
db.<collection>.update({
"$or": [
{ "PropertyA": { "$exists": false } },
{ "PropertyA": null }
]
}, {$set: {"PropertyA": "NewValue"}});
The above code is for one property, but I think you can figure out how to scale it up.
Hope this helps !!

Updating a document without deleting existing values

I have movie model which is referencing a user model by object id.
A user can add or remove itself from the attending list and I'm trying to implement it using mode.findOneAndUpdate.
I read that I should add $set the existing attending user won't get deleted, but even with $set when a user adds himself all the existing users are deleted and now this user is the only one on the list.
Here's the code:
movie model
{
"_id" : ObjectId("fhdfdca5e1b94fafadhfg1"),
"date" : ISODate("2016-10-05T13:56:43.939Z"),
"attending" : [
ObjectId("fhdf6d0e4501f294a6dgd2")
],
"__v" : 0
}
here's my findandupdate:
...
.findOneAndUpdate({_id:req.body.movieId}, {$set:{attending:req.body.imAttending}}, {upsert:true})
How do I simply add an item to my attending list?
TL;DR
use $push not $set if you don't mind repetition in your list or $addToSet for only unique values. see answer and comments below.
Since attending is an array, you should use $push:
.findOneAndUpdate({
_id : req.body.dinnerId
}, {
$push : { attending : req.body.imAttending }
}, ...)
I have had an issue like that before too. When you do find one and update use the set operator like so:
modelname.findOneAndUpdate({
email: var_email},
{ $set: {
token: var_token,
platform: var_platform}},
{ new: true }, function(err, doc)
{
//doc here has updated document, in case you need it.
});
It looks kind of similar to what you have posted. But it should take in some parameters and set them to the current object. If this is incorrect on what you are attempting. Comment below.

Using foreign Keys and mapping to EXTJS

I am using a mongo based DB schema where I have list of ReferenceFields (ObjectIds).
So assume I have two models : User, Group
User Object :
{
"_id" : ObjectId("554ba2897fdd66239457fb33"),
"name" : "something"
}
Group Object :
{
"_id" : ObjectId("453490sdkjskldfjlskdjf"),
"name" : "group_name",
users : [ ObjectId("554ba2897fdd66239457fb33"), ObjectId("554ba28a7fdd66239457fb34") ]
}
ExtJS User Model
Ext.define('Group',{
extend: 'Ext.data.Model',
idProperty : 'id',
fields:[
{name:'group_id', type : 'string', mapping : '_id', persist : false},
{name:'name', type : 'string', mapping : 'name', persist : false}
],
hasMany : { model : 'User', foreignKey:'id' , name : 'users'}
});
The User Model:
Ext.define('User',{
extend: 'Ext.data.Model',
idProperty : 'id',
fields:[
{name:'id', type : 'string', mapping : '_id', persist : false},
{name: 'name', type: 'string'},
]
});
in EXTJS code when I access group.users();
Using the rest method in stores when I add associations to models by giving a foreign Key it fires a GET request to
/users?filter=[{"property":"group_id","value":"453490sdkjskldfjlskdjf","exactMatch":true}]
But this is MySQL kind of association.
How do I solve this to adapt to mongo style of associations?
SO I basically want this to happen. Right now when I call
groups.users().load() it fires a GET request to the Users proxy with the filter params like this
/users?filter=[{"property":"group_id","value":"453490sdkjskldfjlskdjf","exactMatch":true}]. But I don't have group_id in users! So it has to query the users proxy based on the ObjectId it finds inside the users attribute of the group object.
As this is very common in Document based DB, Is this possible by default ? Am I missing something ?
Thanks.
Relationship 1:many in Ext is not implemented the same way as in DBMS. In DBMS we have two tables (a construct similar to store in Ext) and the relationship is defined by foreign keys that link records between tables.
In Ext, we (can) have a store on 1-side (Groups) but we do not have one single store for many-side (Users). Instead, each record of Groups contains a store for Users. It is not exactly a record field for the store but Ext defines a getter.
In your case group.users() returns a store with users that belong to that specific group. Ext behaves exactly same as with any other store when you try to load it: group.users().load() - it only adds filter for that specific foreign key so that you don't need to do it manually.

How to retrieve array of specific field of sub document- mongodb

This is my first mongodb project,I have this document structure in mongodb, I am trying to retrieve a particular user account (each user account has an array of contacts), from this user account, I will then obtain an array of the ID fields of the users contacts and then pass this array as a parameter to another query, I am doing this to avoid having to loop through the users contacts array in order to obtain the ID fields, here is the document structure, the query I tried is below it
{
name,
id,
contacts:[{
contactId, //I need an array of this field
dateAdded
},
contactId,
dateAdded
},
{}..]
}
//
var findByIdAll = function(accountId, callback) {
var self=this;
//Get the user account
Account.findOne({_id:accountId}, function(err,doc) {
/ After the user account has been obtained, the function below will
// use an array of the users contactsId's to fetch the contact's accounts
//please how do I obtain the array of contact Id's before reaching here
self.Account.find({_id:{$in:[/array of contact Ids]}},function(err,results){
callback(results);
});
});
};
EDIT
//I have now been able to obtain an array of contactID fields using the following query
var r=db.accounts.aggregate({$match:{email:'m#live.com'}},{$unwind:"$contacts"},
{$project:{_id:0,contacts:1}},{$group:{_id:'$_id',
list:{$push:'$contacts.accountId'}}});
The result I get from the query is
r
{
"result" : [
{
"_id" : null,
"list" : [
ObjectId("51c59a31c398c40c22000004"),
ObjectId("51c59a31c398c40c22000004")
]
}
],
"ok" : 1
}
A normal MongoDB query will always give you the entire document with the same structure.
If you want to get just part of the document or make a transformation to it you need to use the Aggregation Framework (is not as hard to understand as it looks, give it a try).
In your case you might have to use $unwind in contacts to explode the array, $match to get only the account you want, and $project to present the data as you want.

Using a selfdefined ObjectId and avoiding double entries in Mongoose

I am getting JSON objects through an external API in node.js and want to store them in MongoDB. I defined a model like this:
var Product = new Schema({
id: ObjectId,
name: String});
And now I'm trying to store an object:
JSONProduct = { id: 1234, name: 'The Foo Bar' };
product = new Product(JSONProduct);
product.save();
The object is stored fine in the "products" collection, but the id from the JSONProduct is replaced by a MongoDB created value:
{ "id" : ObjectId("119894980274616772006500"), "name" : "The Foo Bar" }
The main reason why I want to use my Product id over the MongoDB created one is, that I want to prevent duplicate entries for products. I get the JSON Product objects through a cronjob triggered call on an external API, including already existing ones. Maybe there is another, better way to do this?
You are defining an field as an ObjectID, but you are assigning a Number to it. To create an ObjectID you need to do something like:
new ObjectId('something');
However, in your case this is probably not the best idea. Define your model like this:
var Product = new Schema({
external_id: {type: Number, unique: true},
name: {type: String},
});
You can specify unique on a field to create a unique index for that field.
In the question you've mentioned,
The object is stored fine in the "products" collection, but the id from the JSONProduct is replaced by a MongoDB created value:
{ "id" : ObjectId("119894980274616772006500"), "name" : "The Foo Bar" }
But I think the it is created as:
{ "_id" : ObjectId("119894980274616772006500"), "name" : "The Foo Bar" }
Also, you can pass in your product id to field by name "_id", then mongo will not create any separate IDs and it'll not accept duplicate values and it'll have indexing automatically for that field.
But make sure you push unique values of product id to _id.