Can not print child properties of mongodb document with nodejs - json

I have a list of user's documents in mongodb which is carrying fields like this:
{
"_id" : ObjectId("57fb60caf380e20df0d59f4d"),
"signupFp" : "a47d436a33edb44dfd2c45d6eb5574bd",
"signupIp" : "127.0.0.1",
"password" : "d38c2a8589965d869c79ce77e4dc871e",
"email" : "someemail#gmail.com",
"createTime" : ISODate("2016-10-10T09:35:06.386Z"),
"isAdmin" : false,
"isActive" : true,
"account" : [
{
"port" : 5001,
"server" : "harish server"
},
{
"port" : 7001,
"server" : "harish server"
}
],
"__v" : 0,
"sendEmailTime" : ISODate("2016-10-10T09:35:06.405Z"),
"activeKey" : "61ce67b47ee15547878404d9b5bebab7",
"lastLogin" : ISODate("2016-10-12T07:51:53.059Z"),
"expireTime" : ISODate("2016-10-25T00:00:00.000Z")
}
I am fetching all the user's document using nodejs with the following code:
var User = mongoose.model('User');
User.find({}).exec(function(err, data){
if(err){
return;
}
data.forEach(function(user){
if(user.expireTime < new Date()){
console.log(user.lastLogin); //prints the last login date
console.log(user.account); //outputs []
console.log(user.account.port); //outputs undefined
}
}
}
and further i need value of child nodes i.e account.port and account.server but when i console.log its giving me blank array [] or undefined to console.log a specific child key
How do i get the account.port and account.server values

You have specified var User = mongoose.model('User'); you don't need to do it in the logs anymore (user.lastLogin),(user.account),(user.account.port) just omit the user from all of them, should work.
(lastLogin)
(account)
(account.port)

Related

Terraform JSON config error "each.value cannot be used in this context"

My requirement is to create a dynamic resource connector in Kafka cluster. Below is my "connector.tf" file:
resource "confluent_connector" "source" {
environment {
id = confluent_environment.staging.id
}
kafka_cluster {
id = confluent_kafka_cluster.dedicated.id
}
config_sensitive = {
"salesforce.password" : var.source_salesforce_password,
"salesforce.password.token" : var.source_salesforce_password_token,
"salesforce.consumer.key" : var.source_salesforce_consumer_key,
"salesforce.consumer.secret" : var.source_salesforce_consumer_secret
}
config_nonsensitive = {
"connector.class" : "SalesforceCdcSource",
"kafka.auth.mode" : "KAFKA_API_KEY",
"salesforce.cdc.name" : "AccountChangeEvent",
"kafka.api.key" : confluent_api_key.app-manager-kafka-api-key.id,
"kafka.api.secret" : confluent_api_key.app-manager-kafka-api-key.secret,
"salesforce.instance" : var.source_salesforce_url,
"salesforce.username" : var.source_salesforce_username,
for_each = { for s in var.source_salesforce_connector_name : s.source_salesforce_connector_name => s },
"name" : each.value["source_salesforce_connector_name"],
"kafka.topic" : each.value["source_salesforce_topic_name"],
"output.data.format" : each.value["source_salesforce_data_format"],
"tasks.max" : each.value["source_salesforce_max_task"]
}
depends_on = [
confluent_kafka_topic.topic
]
lifecycle {
prevent_destroy = false
}
}
Variable declaration as below: variable.tf file
variable "source_salesforce_connector_name" {
type = list(map(string))
default = [{
"source_salesforce_connector_name" = "SalesforceCdcSourceConnector_0_TF"
}]
}
And I am running this execution from .tfvars file:
source_salesforce_connector_name = [
{
source_salesforce_connector_name = "SalesforceCdcSourceConnector_1_TF"
source_salesforce_topic_name = "json-topic-1"
source_salesforce_data_format = "JSON"
source_salesforce_max_task = "1"
},
]
Getting below error with the execution, please suggest how to pass for_each condition into the JSON configuration as highlighted above.
I tried with above steps and execution, however getting below error:
terraform plan -var-file="DEV/DEV.tfvars"
Error: each.value cannot be used in this context
on modules\confluent_kafka_cluster_dedicated\source_connector_salesforce_cdc.tf line 27, in resource "confluent_connector" "source":
27: "name" : each.value["source_salesforce_connector_name"],
28: "kafka.topic" : each.value["source_salesforce_topic_name"],
29: "output.data.format" : each.value["source_salesforce_data_format"],
30: "tasks.max" : each.value["source_salesforce_max_task"],*
A reference to "each.value" has been used in a context in which it unavailable, such as when
the configuration no longer contains the value in its "for_each" expression. Remove this
reference to each.value in your configuration to work around this error.
If you want multiple confluent_connector resources based on var.source_salesforce_connector_name, then your for_each should be outside of config_nonsensitive:
resource "confluent_connector" "source" {
for_each = { for s in var.source_salesforce_connector_name : s.source_salesforce_connector_name => s },
environment {
id = confluent_environment.staging.id
}
kafka_cluster {
id = confluent_kafka_cluster.dedicated.id
}
config_sensitive = {
"salesforce.password" : var.source_salesforce_password,
"salesforce.password.token" : var.source_salesforce_password_token,
"salesforce.consumer.key" : var.source_salesforce_consumer_key,
"salesforce.consumer.secret" : var.source_salesforce_consumer_secret
}
config_nonsensitive = {
"connector.class" : "SalesforceCdcSource",
"kafka.auth.mode" : "KAFKA_API_KEY",
"salesforce.cdc.name" : "AccountChangeEvent",
"kafka.api.key" : confluent_api_key.app-manager-kafka-api-key.id,
"kafka.api.secret" : confluent_api_key.app-manager-kafka-api-key.secret,
"salesforce.instance" : var.source_salesforce_url,
"salesforce.username" : var.source_salesforce_username,
"name" : each.value["source_salesforce_connector_name"],
"kafka.topic" : each.value["source_salesforce_topic_name"],
"output.data.format" : each.value["source_salesforce_data_format"],
"tasks.max" : each.value["source_salesforce_max_task"]
}
depends_on = [
confluent_kafka_topic.topic
]
lifecycle {
prevent_destroy = false
}
}

how to update an attribute by passing generic variable through body parameter using expressjs

I'm creating a restful API for blog application.
I have to update an attribute of a blog using postman. The object in the database of which an attribute has to be updated looks something like this:
{
"_id": "5a5306a9432f7b12f6e77a21",
"title": "new article",
"_author": {
"username": "linuxuser"
},
"content": "content of the article goes here",
"__v": 0,
"createdAt": "2018-01-08T05:48:41.683Z"
}
I may have to update any attribute but I cannot address it in code dynamically.
Here's the code:
put('/updateblog', function(req, res) {
db.blogModel.findById(req.query.id, function(err, blog) {
if (err) {
res.send(err);
}
blog.title = req.body.title;
// here instead to title i have to update the attribute which is passed through body parameter
blog.save(function(err) {
if (err) {
res.send(err);
}
res.json({
message: "blog updated"
});
});
});
});`
here instead of updating title, I want to update an attribute which is passed through body parameter. I do not know what client is going to send, so, I'm looking for more generic code.
For instance, a user sent a put request to update content attribute, then how do I write code so that corresponding attribute is updated rather than the title like in the above code.
you can get the keys from req.body and iterate or if req.body will contain only the user updated key & value of existing fields in your collection, you can directly use that as update object, but prefer to use some path like req.body.userUpdate for user's updates.
var updateObject = {};
for ( var key in req.body ) { //add logic to filter non existing fields
updateObject[key] = req.body[key] //change path if required
}
once update object has been created use findByIdAndUpdate to update
findByIdAndUpdate(req.query.id, {$set : updateObject } , function(err, blog ) {...}
in mongo CLI
> db.x.find().pretty()
{
"_id" : "5a5306a9432f7b12f6e77a21",
"title" : "new article",
"_author" : {
"username" : "linuxuser"
},
"content" : "content of the article goes here",
"__v" : 0,
"createdAt" : "2018-01-08T05:48:41.683Z"
}
update object
> var mod = {}
> mod['content']='new content'
new content
update
> db.x.update({"_id": "5a5306a9432f7b12f6e77a21"}, {$set : mod}, {$upsert:false})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
output
> db.x.find().pretty()
{
"_id" : "5a5306a9432f7b12f6e77a21",
"title" : "new article",
"_author" : {
"username" : "linuxuser"
},
"content" : "new content",
"__v" : 0,
"createdAt" : "2018-01-08T05:48:41.683Z"
}
>

How to convert a MongoDB document to JSON Object

I am trying to make a post request with the MongoDB document returned from find query, as the request body in NodeJS.But on the server I'm getting the Error : Invalid JSON. Below is the document that I'm trying to POST
{
"_id" : ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount" : 2,
"study" : "cod",
"phase" : "mansa2",
"rhimeTaskId" : "5739a6bec4567f6e737fd3db",
"recordId" : "5726f3cfc4567f6e737fc3ab",
"recordStudy" : "codstudy",
"recordPhase" : "mansa2",
"recordLanguage" : "Punjabi",
"recordScript" : "Latin",
"_state" : "CodingComplete",
"tasks" : [
{
"physician" : ObjectId("5739a6bd3f1b41477570dc78"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Adequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"52 yr male, died of food pipe cancer, suffered pain upper abdomen, investigated,FNAC confirmed Cancer, Put on Chemotherapy, multiple cycles, died at home, had fever with chills occasionally"
]
}
},
{
"physician" : ObjectId("5739a6bd3f1b41477570dc79"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Inadequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"severe pain abdomen, ultrasonography revealed food pipe cancer, chemotherapy given, died"
]
}
}
],
"__v" : 2
}
and here is the code that I wrote to make the POST request
var MongoClient = require('mongodb').MongoClient;
var request = require('request');
var assert = require('assert');
var cmeprovisioning= 'mongodb://localhost:27017/cmeprovisioning';
MongoClient.connect(cmeprovisioning, function(err, db) {
assert.equal(null, err);
var count=0;
console.log("Connected to cmeprovisioning");
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"
});
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
console.dir(doc);
count=count+1;
request({url: "http://cme.host.net:8081/cme-provisioning/update",
method: "POST",json: true,
headers: {"content-type": "application/json"},
json: doc
},function(e,r,b){
console.log("POST Error "+count+" "+e)
console.log("POST Response "+count+" "+r)
console.log("POST BODY "+count+" "+b)
});
} else {
console.log("Some Error : "+err)
}
});
});
I also tried using JSON.stringify(doc), but still got the Invalid JSON error. Is there a way I can use mongo document returned by the find query and convert it to JSON to make the POST request.
I think those ObjectID is what making it an invalid JSON document.
Here's the actual answer:
If you want to convert a mongo object to JSON object.
There's a utility method in every mongo object toJSON
So you can simply do mongoResponseObject.toJSON() on the response object.
e.g.
Products.findById(id).then(res => {
const jsonRes = res.toJSON();
// Here jsonRes is JSON
})
Alternatively you can directly get the JSON object by using the .lean() like this.
Products.findById(id).lean().then(res => {
// Here res is JSON
})
you need to convert object id to string ie.
var result = {
"_id": ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount": 2,
"study": "cod"
};
//now convert to string
result=result._id.toString();
//now you can use the result
Try this,
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"});
cursor.toString();
......
Hope this help.
Try this in robomongo
var cursor = db.getCollection('X').find({},{})
while(cursor.hasNext()) {
print(JSON.stringify(cursor.next()))
}

How do you insert an array of object into Mongodb node.js

Basically i want to insert into my Mongodb collection called "Events" an array of objects called "Events" with an id for each entry into the array.
This is the result i want to get in json:
{
"events" : [
{
"_id" : ObjectId("53a99cc608ad49712a830081"),
"eTitle" : "Freshers Fair",
"eDesc" : "Bring some friends with you oh wait, you have non ha !",
"eDate" : "2014-06-19 11:20",
"eLink" : "http://fair.com",
"eEvent" : "NEFS"
},
{
"_id" : ObjectId("53a99cc608ad49712a830082"),
"eTitle" : "Blahh",
"eDesc" : "Blah fdinidf !",
"eDate" : "2014-06-19 11:20",
"eLink" : "http://google.com",
"eEvent" : "NEFS"
}
]
}
So far this is the result i have:
[
{
"_id":"53a9b5ed745363432d823d7a",
"eTitle":"jrnfdeiujn rd",
"eDesc":"grfdsreds",
"eDate":"2014-07-05 22:33",
"eLink":"reser",
"eEvent":"Victoria Center"
},
{
"_id":"53a9b771745363432d823d7b",
"eTitle":"Hello worlds",
"eDesc":"blah",
"eDate":"2014-07-20 22:33",
"eLink":"http://google.com",
"eEvent":"social"
}
]
This is how i insert data with node.js:
// Set our collection
var collection = db.get('Events');
// Submit to the DB
collection.insert({
"eTitle" : eTitle,
"eDesc" : eDesc,
"eDate" : eDate,
"eLink" : eLink,
"eEvent" : eEvent
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem adding the information to the database.");
}
else {
// If it worked, set the header so the address bar doesn't still say /adduser
res.location("eventlist");
// And forward to success page
res.redirect("eventlist");
}
});
So please i how do i make the format look this the first json format i provided. sorry for the nooby question, just started learning node ! Thanks alot
UPDATE
To post Events:
router.get('/eventlist', function(req, res) {
var db = req.db;
var collection = db.get('Events');
collection.find({},{},function(e,docs){
console.log(docs);
res.send(docs);
// res.render('eventlist', {docs: JSON.stringify(docs), title: 'Test'});
});
});
You can do this:
collection.find({},{},function(e,docs){
var doc = { Events : docs };
console.log(doc);
res.send(doc);
// res.render('eventlist', {docs: JSON.stringify(docs), title: 'Test'});
});

RKEntityMapping JSON array RKResponseDescriptor keypath issue possibly

I am attempting to map my Core Data "Component" Entity to the "hotspots" keypath in this response JSON, but it only gets to the array object so it will not map. I can't tell if my problem is the mapping or the response descriptor or a combination of the two.
"result" : {
"type" : "Slidedeck",
"id" : 81,
"name" : "Brendantest",
"slides" : [
{
"thumb" : "http:\/\/api.idetailapp.review.thingee.com\/v4\/resources\/1294\/download\/slide?thumb=true",
"id" : 1294,
"notes" : "",
"label" : "",
"order" : 1,
"parent_id" : 81,
"file" : "slide-20.jpg",
"components" : {
"hotspots" : [
{
"x" : 205,
"options" : "embedded",
"type" : "video",
"id" : 6082,
"y" : 453,
"assets" : [
{
"thumb" : "\/system\/asset_objects\/14\/original_thumb\/14.png",
"id" : 14,
"parent_id" : 6082,
"file" : "slide_15_chart_animation_ipad_r03.mov",
"url" : "http:\/\/api.idetailapp.review.thingee.com\/v4\/resources\/14\/download\/asset"
}
],
"parent_id" : 1294,
"width" : 320,
"height" : 246
}
]
},
"url" : "http:\/\/api.idetailapp.review.thingee.com\/v4\/resources\/1294\/download\/slide"
}
],
"version" : "0.43"
}
}
Here is my RKEntityMapping:
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:#"Component"
inManagedObjectStore:[RKManagedObjectStore defaultStore]];
mapping.identificationAttributes = #[ #"componentID" ];
[mapping addAttributeMappingsFromDictionary:#{#"id": #"componentID",
#"parent_id": #"parentID"
}];
[mapping addAttributeMappingsFromArray:#[#"x", #"y", #"width", #"height", #"type", #"options"]];
Here is my Responsedescriptor:
componentResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:componentEntityMapping
method:RKRequestMethodAny pathPattern:nil
keyPath:#"result.slides.components.hotspots" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
I put in a RestKit/ObjectMapping debug trace and get to the following output:
Asked to map source object (
{
assets = (
{
file = "slide_15_chart_animation_ipad_r03.mov";
id = 14;
"parent_id" = 6082;
thumb = "/system/asset_objects/14/original_thumb/14.png";
url = "http://api.idetailapp.review.thingee.com/v4/resources/14/download/asset";
}
);
height = 246;
id = 6082;
options = embedded;
"parent_id" = 1294;
type = video;
width = 320;
x = 205;
y = 453;
}
And further debug message of:
Failed transformation of value at keyPath 'id' to representation of type 'NSNumber': Error Domain=org.restkit.RKValueTransformers.ErrorDomain Code=3002 "Failed transformation of value '(
6082
)UserInfo=0x12479350 {NSLocalizedDescription=Expected an inputValue of type NSNull, but got a __NSArrayI.}"
),
Your problem is keyPath:#"result.slides.components.hotspots".
Specifically, the fact that slides is an array.
The result is that RestKit is asked to map an array of objects into your mapping. So, when it tries to get the id (which should be a number), it gets an array (hence your error). This is because calling valueForKey: on an array returns an array...
So, basically, you can't do it the way you're trying to because of the array in the middle of the JSON.
If you can get the JSON changed, do that. If you can't, you need to change your mapping to map the slides first and then the nested components (then you can discard the slides afterwards if you want).