how to append data in mongo db using rails - mongodb

I am using rails 4.1.8 along with ruby 2.1.2p95 and mongo-2.0.4 gem to connect to mongo db v3.0.3. I have read this document but it doesn't provide how do we append the data in the existing row of a document. Also, can anyone provide the any other link of document which provide the extensive syntax to connect to mongo from rails.
following code will not append the data, rather it will create a new row:
mongo_con.find(:chatid => 5678).update_one('$set' => {:chat => 'this is are you'})
Code :
require 'mongo'
db = Mongo::Client.new([ '192.168.56.102:27017' ], :database => 'stackoverflow')
After inserting the following row :
{ "_id" : ObjectId("55698e906e6172193f000001"), "id" : 5678, "message" : "Hey, how are you", "type" => 1, "timestamp" => 4567723456789 }
I want to append this row in the previous one:
{ "_id" : ObjectId("5561d03f7979393062b18bf9"), "id" : 5678, "message" : "I am good", "type" => 2, "timestamp" => 654313687989 }

Related

Adding to a double-nested array in MongoDB

I have a double nested array in my MongoDB schema and I'm trying to add an entirely new array element to a second-level nested array using $push. I'm getting the error cannot use the part (...) to traverse the element
A documents have the following structure
{
"_id" : ObjectId("5d8e37eb46c064790a28a467"),
"org-name" : "Manchester University NHS Foundation Trust",
"domain" : "mft.nhs.uk",
"subdomains" : [ {
"name" : "careers.mft.nhs.uk",
"firstSeen" : "2017-10-06 11:32:00",
"history" : [
{
"a_rr" : "80.244.185.184",
"timestamp" : ISODate("2019-09-27T17:24:57.148Z"),
"asn" : 61323,
"asn_org" : "Ukfast.net Limited",
"city" : null,
"country" : "United Kingdom",
"shodan" : {
"ports" : [
{
"port" : 443,
"versions" : [
"TLSv1",
"-SSLv2",
"-SSLv3",
"TLSv1.1",
"TLSv1.2",
"-TLSv1.3"
],
"cpe" : "cpe:/a:apache:http_server:2.4.18",
"product" : "Apache httpd"
}
],
"timestamp" : ISODate("2019-09-27T17:24:58.538Z")
}
}
]
}
]
}
What I'm attempting to do is refresh the details held in the history array and add another entire array entry to represent the most recently collected data for the subdomain.name
The net result is that I will have multiple entries in the history array, each one timestamped the the date that the data was refreshed. That way I have a historical record of changes to any of the data held.
I've read that I can't use $push on a double-nested array but the other advice about using arrayfilters all appear to be related to updating an entry in an array rather than simply appending an entirely new document - unless I'm missing something!
I'm using PyMongo and would simply like to build a new dictionary containing all of the data elements and simply append it to the history.
Thanks!
Straightforward in pymongo:
record = db.mycollection.find_one()
record['subdomains'][0]['history'].append({'another': 'record'})
db.mycollection.replace_one({'_id': record['_id']}, record)

MongoDB : best way to storing key value data

I have to migrate from MySQL to MongoDB , and i beginner in MongoDB, what is the best way to storing below data in MongoDB ?
should i create a document for each row?
should i save all row in a one document?
Which one is valid way in MongoDB?
{
"_id" : ObjectId("5659d56fef6c702fbc45cc1b")
"key" : "setting_update_id"
"value" : "1"
"extra" :
[
//some data
]
}
OR
{
"_id" : ObjectId("5659d56fef6c702fbc45cc1b")
"setting_update_id" : "1"
"extra" :
[
//some data
]
}
Ali,
As a beginner you would want to read the docs here. Each collection can be thought of roughly as a table in a relational database. And each document can be thought of as a row in the database. So each column of your table would be the keys of your document.
I would design it closer to the first one.
{
"_id" : ObjectId("5659d56fef6c702fbc45cc1b")
"key" : "setting_update_id"
"value" : "1"
"params" :
{
"extra" : "hello",
"foo" : "bar"
}
}

Insert nested document using Reactivemongo, Play framework and Scala

I am new to Play framework 2.3 using scala and reactivemongo. I have already developed few pages to load data from forms into mongodb.
So far so good. But now I’m planning to use nested document feature of mongodb as there is no direct support for JOINS in mongodb. I am aware of manual reference and DB refs way joining collections in MongoDB.
There are some questions posted on this forum related to nested documents in mongodb but they are of no help to me.
I would really appreciate if you can show me, how to insert and update sub-documents in the already existing document in mongodb collection using play framework, scala and reactivemongo?
The structure of the data is as follows:
"_id" : ObjectId("5516ae699aaebdfc0bc47f7d"),
"name" : "ABCD",
"address" : "Blue Skies",
"dob" : 135962900000,
"email" : ""
And I would like to add new sub-document entries as follows:
"_id" : ObjectId("5516ae699aaebdfc0bc47f7d"),
"name" : "ABCD",
"address" : "Blue Skies",
"dob" : 01/01/1970,
"email" : "",
“visits” : [
{
“date” : 18/02/2015,
“comments” : “Some comments”,
“createdBy” : “XYZ”
},
{
“date” : 23/03/2015,
“comments” : “Some comments”,
“createdBy” : “PQR”
}
]
Here’s how my code for updating a document in a collection looks like:
def updateData(id: String) = Action.async { implicit request =>
projectForm.bindFromRequest.fold(
formWithErrors => Future.successful(BadRequest(html.editProject(id, formWithErrors))),
project => {
val futureUpdateProj = collection.update(Json.obj("_id" -> Json.obj("$oid" -> id)), project.copy(_id = BSONObjectID(id)))
futureUpdateProj.map { result =>
projectsHome.flashing("success" -> s"Project ${project.name} has been updated")
}.recover {
case t: TimeoutException =>
Logger.error("Problem found in Project update process")
InternalServerError(t.getMessage)
}
})
}

MongoDB Aggregation: Value in Array

We have the following Testsnippet in Ruby
def self.course_overview(course_member=nil)
course_member = CourseMember.last if course_member == nil
group_global = {"$group" =>
{"_id" => { "course_id" => "$course_id",
"title" => "$title",
"place" => "$place",
"description" => "$description",
"choosen_id" => "$choosen_id",
"year" => {"$year" => "$created_at"},
"course_member_ids" => "$course_member_ids"}}
}
match_global = {"$match" => {"_id.course_member_ids" => {"$in" => "#{course_member.id}"} }}
test = CoursePlan.collection.aggregate([group_global, match_global])
return test
end
The problem is the "match_global" statement. We would like to match all Documents where the course_member ID is appearing in the course_member_ids array.
The above statement fails with the error: "...must be an array". This make sense to me but according to other comments on the web this should be possible this way.
Any advice? How is it possible to return the docs where the course_member id is in the array of the course_member ids?
Sample CoursePlan Object:
{
"_id" : ObjectId("5371e70651a53ed5ad000055"),
"course_id" : ObjectId("5371e2e051a53ed5ad000039"),
"course_member_ids" : [
ObjectId("5371e2a751a53ed5ad00002d"),
ObjectId("5371e2b251a53ed5ad000030"),
ObjectId("5371e2bb51a53ed5ad000033")
],
"created_at" : ISODate("2014-05-13T09:33:58.042Z"),
"current_user" : "51b473bf6986aee9c0000002",
"description" : "Schulung 1 / Elektro",
"fill_out" : ISODate("2014-04-30T22:00:00.000Z"),
"place" : "TEST",
"title" : "Schulung 1",
"updated_at" : ISODate("2014-05-13T09:33:58.811Z"),
"user_ids" : [
ObjectId("51b473bf6986aee9c0000002"),
ObjectId("521d7f606986ae4826000002"),
ObjectId("521d8b3f6986aed678000007")
]
}
Since course_member_ids is an array of course members you should test for equality. In shell syntax:
{$match:{"_id.course_member_ids":<valueYouWantToTest>}}
You don't need $in as this query is analogous to a find when you want to select documents that have a particular single value you are looking for.

Select latest documents in MongoDB

My app records some data in MongoDB collection. There are three types of events: 'event1', 'event2', 'event3'. And this elements adds periodically.
Event structure example:
{ 'Data' : 'a234235', 'Type' : 'event1', 'Timestamp' : 1366006599 }
{ 'Data' : 'b978543', 'Type' : 'event2', 'Timestamp' : 1366006600 }
{ 'Data' : 'c567921', 'Type' : 'event3', 'Timestamp' : 1366006601 }
{ 'Data' : 'd327863', 'Type' : 'event1', 'Timestamp' : 1366007100 }
{ 'Data' : 'e012315', 'Type' : 'event2', 'Timestamp' : 1366007102 }
{ 'Data' : 'f834721', 'Type' : 'event3', 'Timestamp' : 1366007103 }
Please help compose right query for get current state of each event in database. I need three elements of different types and maximal timestamp.
Since you may have ~200 events (as noted in your comments on the question), I would suggest the most efficient approach would be to create a summary document that records the latest events (by type). This avoids the needs to do separate queries and should be easy to maintain using a $set as new event types are observed.
The summary doc would look like:
{
'Event1' : { 'Data' : 'd327863', 'Timestamp' : 1366007100 },
'Event2' : { 'Data' : 'e012315', 'Timestamp' : 1366007102 },
'Event3' : { 'Data' : 'f834721', 'Timestamp' : 1366007103 }
}
This pre-aggregated report pattern will avoid the need for multiple queries if you often need to find the maximal event by type, and save on (potentially large) space for an index on Timestamp which would otherwise be needed to find the latest entry efficiently.
You can use the following JavaScript to get your work done. The drawback here is that I am assuming your events are constant else you need to change this in the "Type" array field.
You can invoke this while connecting to DB.
a=function()
{
var Type = new Array();
Type[0]="event1";
Type[1]="event2";
Type[2]="event3";
Type[3]="event4";
Type[4]="event5";
for (i=0;i<Type.length;i++)
{
var myCursor = db.foo.find({Type:Type[i]}).sort({Timestamp:-1}).limit(1);
myCursor.forEach(printjson);
}
}
and this is the output I got for my test case.
MongoDB shell version: 2.2.2
connecting to: test
{
"_id" : ObjectId("516bc991cde2925693705103"),
"Data" : "d327863",
"Type" : "event1",
"Timestamp" : 1366007100
}
{
"_id" : ObjectId("516bc991cde2925693705104"),
"Data" : "e012315",
"Type" : "event2",
"Timestamp" : 1366007102
}
{
"_id" : ObjectId("516bc992cde2925693705105"),
"Data" : "f834721",
"Type" : "event3",
"Timestamp" : 1366007103
}
bye
Also note that, by default it connects to test db. Indexing on Type and Timestamp will help you in performance.
You will need a separate query for each event.
db.yourCollection.find({Type:"event1"}).sort({Timestamp:-1}).limit(1);
db.yourCollection.find({Type:"event2"}).sort({Timestamp:-1}).limit(1);
db.yourCollection.find({Type:"event3"}).sort({Timestamp:-1}).limit(1);
Note that creating an index on the Timestamp field will likely improve the performance a lot.
See also: http://docs.MongoDB.org/manual/reference/method/cursor.sort/