Add key value pair data - node.js

I have a schema in Mongoose that looks like this:
const SocketDetailsUserSchema = new mongoose.Schema({
userId: String,
socketValue: [{
id: String,
data : String
}],
isDeleted: Boolean,
dateCreated: Date,
updateAt: Date
});
I want to insert data of socketValue in key value pair in array format. Which should look like ,
{
"_id" : ObjectId("5a12809c7f7afb1e3626857f"),
"userId" : "59eee19696fe6560cd54a081",
"socketValue" : [{"id":"5a05855b10600e4aa5b3a48e" , "value" : "123" }],[{"id":"5a0ae037a90746c249b6c1f7" , "value" : "456" }],
"isDeleted" : false
"__v" : 0
}
This is the mongoose data format.
How can i insert data in mongoose like this ?
I am also confused that how should i post data from postman to insert data in this ?

I think your current structure is good just add _id: false to avoid to add auto generated _id in socketValue. like
socketValue: [{
id: String,
data : String,
_id: false
}],
for this structure data will store like:
"socketValue" : [{"id":"5a05855b10600e4aa5b3a48e" , "value" : "123" },{"id":"5a0ae037a90746c249b6c1f7" , "value" : "456" }]"
then you can easily update or add new socketValue. I think this [{..},{..},{..}] is the better structure instead of [[{..}][{..}]] this structure.
and for this structure postman request body should contain like.
{
"userId" : "59eee19696fe6560cd54a081",
"socketValue" : [{"id":"5a05855b10600e4aa5b3a48e" , "value" : "123" },{"id":"5a0ae037a90746c249b6c1f7" , "value" : "456" }]",
"isDeleted" : false
}
and in your server side code just use like
var newSocket = new Socket(req.body); // assume your model name is Socket
newSocket.save();

Your postman input data should be raw json format
{
"userId" : "59eee19696fe6560cd54a081",
"socketValue" : [{"id":"5a05855b10600e4aa5b3a48e" , "value" : "123" },{"id":"5a0ae037a90746c249b6c1f7" , "value" : "456" }]",
"isDeleted" : false
}
Your server code
var insertDoc = new collectionname(details);
inserDoc.save(function (err) {
if (err) {
//callback err
} else {
//callback result
}
});

Related

Mongodb update field inside object array with one condition

I have the following field inside my mongo documents
"offers" : [
{
"price" : 15,
"Date1" : 1661385600000.0,
"fullname" : "name 1",
"isDeleted" : false,
"createdDate" : 1660660090798.0,
"expired" : false
},
{
"price" : 40,
"Date1" : 1661388600000.0,
"fullname" : "name 2",
"isDeleted" : false,
"createdDate" : 1660660090788.0,
"expired" : false
}
],
And I want to map all the objects inside the array of all documents in the DB and compare the field createdDate with the current date, if this comparison is true, I want to change the expired field value.
What I did was use updateMany method and in the update param I used $exist $ne and $lt operators to make the logic.
And the code was the following:
let today = new Date();
let twoDayAgo = today.setDate(today.getDate()-2); //subtracting 2 days from today's date
let orderCriteria = {
orderStatus : "STATUS_THAT_I_WHANT_TO_FIND",
offers : { $exists: true, $ne: [] },//if find the order by status, proving that the key offers exist and is not empty
isDeleted : false,
"offers.createdDate" : { $lt: twoDayAgo } //compares the value with twoDaysAgo variable
};
let data2Updat = {
$set: {
"offers.$.expired" : true
}
}
let result = await DAOManager.updateMany( Model, orderCriteria, data2Updat, {} )

console.logging data from MongoDB

I am still trying to comprehend Mongoose/Mongo
Now in terminal When I do something like this in terminal
use library
show collections
db.authors.find().pretty()
I get something like this in logged
{
"_id" : ObjectId("5bc8704f3a9828d5513505a2"),
"name" : "Aman",
"age" : "21",
"__v" : 0
}
{
"_id" : ObjectId("5bc870553a9828d5513505a3"),
"name" : "Rohit",
"age" : "20",
"__v" : 0
}
{
"_id" : ObjectId("5bc8704f3a9828d5513505a7"),
"name" : "Aman",
"age" : "21",
"__v" : 0
}
{
"_id" : ObjectId("5bc870553a9828d5513505a5"),
"name" : "Rohit",
"age" : "20",
"__v" : 0
}
Now, I want to have same data in my NodeJs i.e say, I want to find wherever the name is Rohit and want to link it with with some other db or schema.
how can I get the same output which I just obtained by running the above given command in terminal window of mongo in NodeJS
Obviously doing something like this console.log(db.authors.find()) won't work, so how can I get that?
This is how I usually write my database queries.
First create a schema that your model will follow. Don't worry this schema is flexible and you can change it at any time without affecting old data.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var authorSchema = new Schema({
name: {
type: String,
required: true
},
age: {
type: Number,
default: 20
}
});
Next create a model from your schema.
var authorModel = mongoose.model('authorModel', authorSchema);
Lastly query your model and get the value you need
authorModel.find(
{
name: 'Rohit'
},
function (err, result) {
console.log(result)
});
I put my schema and controller on separate files. How you organise your code structure is up to you.
I pretty much followed this blog when I first learnt to build APIs on NodeJS. You might find this useful as well!

MongoDB query on join

This is an abstract example, but if someone can help me to solve it, I will be eternally grateful.
I am trying to do a search based on a field in a related record. In this example we have a hierarchy of subjects, that are nested using the parent_subject field. This is the Mongoose definition I have used:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var subjectSchema = new Schema({
url: { type: String, required: true, unique: true },
title: { type: String, required: true, unique: true },
parent_subject: this
});
module.exports = mongoose.model('Subject', subjectSchema);
Some records in my MongoDB:
{
"_id" : ObjectId("5a3857f1afeb498c9533aef1"),
"title" : "Sport",
"url" : "sport",
"__v" : 0
},
{
"_id" : ObjectId("5a3d9a409c0973976f7889c6"),
"title" : "Cycling",
"__v" : 0,
"parent_subject" : ObjectId("5a3857f1afeb498c9533aef1"),
"url" : "cycling"
},
{
"_id" : ObjectId("5a3d9a7e9c0973976f788b48"),
"title" : "Mountain Biking",
"__v" : 0,
"parent_subject" : ObjectId("5a3d9a409c0973976f7889c6"),
"url" : "mountain biking"
}
I would like to know how I can query this data based on a field in the parent record. For example, I would like to find all the subjects that have a parent subject with the title "Sport". In SQL, I would do the following query:
SELECT *
FROM subject
INNER JOIN subject AS parentSubject
ON subject.parent_subject = parentSubject.id
WHERE parentSubject.title = "Sport";
How would I achieve this with a MongoDB?
You can use mongodb aggregate pipeline and lookup for this
`Subject.aggregate([
{
$lookup:
{
from: "parentSubject",
localField: "parent_subject",
foreignField: "id"
as: "parentSubject"
}
},
{$unwind:"$parentSubject"},
{$match:{"$parentSubject.title":"Sport"}}
])`
For more reference you can see https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/index.html
The point of mongoDB is that it is NOSQl, so that you also cannot use joins.
Your best option would be to first acquire the parentSubject and it's id.
And afterwards go for the subjects related to that id.
Since your data already has a subject.parent_subject it should be pretty easy to do.

Fetch sub-document Mongodb only match with criteria

I have data in mongodb like this:
{
"_id" : ObjectId("55a12bf6ea1956ef37fe4247"),
"tempat_lahir" : "Paris",
"tanggal_lahir" : ISODate("1985-07-10T17:00:00.000Z"),
"gender" : true,
"family" : [
{
"nama" : "Robert Deniro",
"tempat_lahir" : "Bandung",
"tanggal_lahir" : ISODate("2015-07-09T17:00:00.000Z"),
"pekerjaan" : "IRT",
"hubungan" : "XXX",
"tanggungan" : false,
"_id" : ObjectId("55a180f398c9925299cb6e90"),
"meta" : {
"created_at" : ISODate("2015-07-11T20:59:25.242Z"),
"created_ip" : "127.0.0.1",
"modified_at" : ISODate("2015-07-12T15:54:39.682Z"),
"modified_ip" : "127.0.0.1"
}
},
{
"nama" : "Josh Groban",
"tempat_lahir" : "Jakarta",
"tanggal_lahir" : ISODate("2015-06-30T17:00:00.000Z"),
"pekerjaan" : "Balita",
"hubungan" : "Lain-Lain",
"tanggungan" : true,
"_id" : ObjectId("55a29293c65b144716ca65b2"),
"meta" : {
"created_at" : ISODate("2015-07-12T16:15:15.675Z"),
"created_ip" : "127.0.0.1"
}
}
]
}
when i try to find data in sub-document, with this code:
person.findOne({ _id: req.params.person, {'family.nama': new RegExp('robert', 'gi') }}, function(err, data){
// render code here
});
It show all data in Family Data,
Can we fetch or display a data only match with criteria/keyword, for example only "Robert Deniro" row
Thank You
In 'regular' MongoDB, you can use the $ operator for that. I'm not sure if it works with Mongoose, but it's worth a try:
person.findOne({
_id : req.params.person,
'family.nama' : new RegExp('robert', 'gi')
}, {
// Only include the subdocument(s) that matched the query.
'family.$' : 1
}, function(err, data){
// render code here
});
If you need any of the properties from the parent document (tempat_lahir, tanggal_lahir or gender; _id will always be included), you need to add them to the projection object explicitly.
One caveat: the $ operator will only return the first matching document from the array. If you need it to return multiple documents, you can't use this method and (AFAIK) have to postprocess the results after they are returned from the database.
It solved with this code:
var options = {
family: {
$elemMatch: { nama: req.query.keyword }
},
};
person.findOne({ _id: req.params.person, 'family.nama': keyword }, options, function(err, data){
//render code here
});
Thanks to #hassansin & #robertklep

NodeJS + Mongoose + Backbone.Marionette nested Collection templating

all
I'm developing an application that store my multimedia catalog, I've JSON collection like this :
{ "_id" : ObjectId( "5142f55394474e2aac000001" ),
"contentType" : "binary/octet-stream",
"length" : 2732376,
"chunkSize" : 262144,
"uploadDate" : Date( 1363342677601 ),
"metadata" : {
"TIT2" : "Chase The Blues (Cameron McVey Remix)",
"TPE1" : "Terranova",
"TRCK" : "1/13",
"TALB" : "!K7",
"TPOS" : "1/1",
"TDRC" : "2000-06",
"TCON" : [
"Electronica",
"Trip-Hop" ],
"COMM" : [
"Chillout",
"Love",
"German",
"Berlin",
"2000s",
"Female Vocalists",
"Male Vocalists" ],
"TMED" : "CD",
"TMOO" : "Chill",
"TDOR" : "2000-06",
"TSO2" : "Various Artists",
"TPE2" : "Various Artists",
"TCMP" : "1",
"TSOP" : "Terranova",
"TIT1" : "Electronica",
"TPUB" : "Sinedín Music",
"TLAN" : "eng",
"TYER" : [
"2000" ],
},
"md5" : "617401af615ac0c6cb1dee9a3f1b99e6",
"origin" : "Chase The Blues.109eb5ab5105a1caa505a26657f7f9a8.mp3",
"evolution" : null,
"insertDate" : Date( 1336662308000 ),
"tagSource" : "MusicBrainz",
"mediainfo" :
{ "Format" : "MPEG Audio",
"Format version" : "Version 1",
"Format profile" : "Layer 3",
"Duration" : "3mn 47s",
"Bit rate mode" : "Constant",
"Bit rate" : "96.0 Kbps",
"Channel(s)" : "1 channel",
"Sampling rate" : "44.1 KHz",
"Compression mode" : "Lossy",
"Stream size" : "2.60 MiB (100%)",
"Language" : "English"
}
}
so, as you can see, there are "metadata" and "mediainfo" array in the document
in the models.js , in the client side, I've rewrite the model parse function like this
var Audio_Model = Backbone.Model.extend({
idAttribute: "_id",
url: 'AudioModel',
urlRoot: 'AudioModel' ,
parse: function(response) {
// Check if response includes some nested collection data...
if (_.has(response, 'metadata')){
// Check if this model has a property called metadata
if (!_.has(this, 'metadata')) { // It does not...
// So instantiate a collection and pass in raw data
this.metadata = new Audio_Collection_Metadata(response.metadata);
} else {
// It does, so just reset the collection
this.metadata.reset(response.metadata);
}
delete response.metadata;
}
// Check if response includes some nested collection data...
if (_.has(response, 'mediainfo')){
// Check if this model has a property called mediainfo
if (!_.has(this, 'mediainfo')) { // It does not...
// So instantiate a collection and pass in raw data
this.mediainfo = new Audio_Collection_Mediainfo(response.mediainfo);
} else {
// It does, so just reset the collection
this.mediainfo.reset(response.mediainfo);
}
delete response.mediainfo;
}
return response;
}
});
so I've created two separate collection of 'metadata' and 'mediainfo'
the problem that I've is how to render 'metadata' and 'mediainfo' in html template because in 'mediainfo' and 'metadata' collection the key, values are not fixed and in 'metadata' some keys are array of values and the number of item in the array are not fixed
I've created backbone.marionette.itemview and compositeview for these two collections but I don't know how to render
Plase, someone have a solutions ?
Best Regards
finally I've fixed the problem myself with a data normalization, this is the new mongoose schema adopted :
var TagSchema = new mongoose.Schema({
value : {type : String, default: '', required: true}
});
var MetadataSchema = new mongoose.Schema({
name : {type: String, default: '', required : true},
values: [TagSchema]
});
var MediainfoSchema = new mongoose.Schema({
name : {type: String, default: ''},
value: {type: String, default: ''}
});
var StreamSchema = new mongoose.Schema({
_id: mongoose.Schema.ObjectId,
TIT2: {type : String, default: '', required: true},
metadata: [MetadataSchema],
mediainfo:[MediainfoSchema]
});
so that with sequence of CollectionView and CompositeView I can browse the entire model
Hope this can help someone

Resources