Insert nested document using Reactivemongo, Play framework and Scala - mongodb

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)
}
})
}

Related

MongoDB WildCard query taking too much time using Grails

MongoDB v4.0.2
Grails 3.3.5
I've more than 20 Millions of records stored in a collection. I'm trying to wildcard search in that collection like as follows...
def personList = Person.collection.find(['vehicleNumber': ['$regex':/.*GJ18AD.*/] ]).sort(["datetime":-1])
Index on Person Collection
db.person.getIndexes()
{
"v" : 2,
"key" : {
"vehicleNumber" : 1
},
"name" : "vehicleNumber_1",
"ns" : "analytics.person",
"weights" : {
"numberPlate" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
Is there any other way for the wildcard search?
There is no changes required in the indexing. But the minor change in the filter Object which I'm passing to the collection.
Previously, I was using following filter object syntax:
def personList = Person.collection.find(['vehicleNumber': ['$regex':/.*GJ18AD.*/] ]).sort(['datetime':-1])
Then I've change only the regex in the above syntax:
def personList = Person.collection.find(['vehicleNumber': ['$regex':'.*GJ18AD.*'] ]).sort(['datetime':-1])
It's works for me in the MongoDB version 4.2.1.

Find by sub-documents field value with case insensitive

I know this is a bit of newb question but I'm having a hard time figuring out how to write a query to find some information. I have several documents (or orders) much like the one below and I am trying to see if there is any athlete with the name I place in my query.
How do I write a query to find all records where the athleteLastName = Doe (without case sensitivity)?
{
"_id" : ObjectId("57c9c885950f57b535892433"),
"userId" : "57c9c74a0b61b62f7e071e42",
"orderId" : "1000DX",
"updateAt" : ISODate("2016-09-02T18:44:21.656Z"),
"createAt" : ISODate("2016-09-02T18:44:21.656Z"),
"paymentsPlan" :
[
{
"_id" : ObjectId("57c9c885950f57b535892432"),
"customInfo" :
{
"formData" :
{
"athleteLastName" : "Doe",
"athleteFirstName" : "John",
"selectAttribute" : ""
}
}
}
]
}
You need to use dot notation to access the embedded documents and regex because you want case insensitive.
db.collection.find({'paymentsPlan.customInfo.formData.athleteLastName': /Doe/i}

Zipping two collections in mongoDB

Not a question about joins in mongoDB
I have two collections in mongoDB, which do not have a common field and which I would like to apply a zip function to (like in Python, Haskell). Both collections have the same number of documents.
For example:
Let's say one collection (Users) is for users, and the other (Codes) is of unique randomly generated codes.
Collection Users:
{ "_id" : ObjectId(""), "userId" : "123"}
{ "_id" : ObjectId(""), "userId" : "456"}
Collection Codes:
{ "_id" : ObjectId(""), "code" : "randomCode1"}
{ "_id" : ObjectId(""), "code" : "randomCode2"}
The desired output would to assign a user to a unique code. As follows:
Output
{ "_id" : ObjectId(""), "code" : "randomCode1", "userId" : "123"}
{ "_id" : ObjectId(""), "code" : "randomCode2", "userId" : "456"}
Is there any way of doing this with the aggregation pipeline?
Or perhaps with map reduce? Don't think so because it only works on one collection.
I've considered inserting another random id into both collections for each document pair, and then using $lookup with this new id, but this seems like an overkill. Also the alternative would be to export and use Python, since there aren't so many documents, but again I feel like there should be a better way.
I would do something like this to get the records from collection 1 & 2 and merge the required fields into single object.
You have already confirmed that number of records in collection 1 and 2 are same.
The below code will loop through the cursor and map the required fields into one object. Finally, you can print the object to console or insert into another new collection (commented the insert).
var usersCursor = db.users.find( { } );
var codesCursor = db.codes.find( { } );
while (usersCursor.hasNext() && codesCursor.hasNext()) {
var user = usersCursor.next();
var code = codesCursor.next();
var outputObj = {};
outputObj ["_id"] = new ObjectId();
outputObj ["userId"] = user["userId"];
outputObj ["code"] = code["code"];
printjson( outputObj);
//db.collectionName.insertOne(outputObj);
}
Output:-
{
"_id" : ObjectId("58348512ba41f1f22e600c74"),
"userId" : "123",
"code" : "randomCode1"
}
{
"_id" : ObjectId("58348512ba41f1f22e600c75"),
"userId" : "456",
"code" : "randomCode2"
}
Unlike relational database in MongoDB you doing JOIN stuff at the app level (so it will be easy to horizontal scale the database). You need to do that in the app level.

how to append data in mongo db using rails

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 }

Insert new record using Scala Salat/Casbah and Mongodb

Greetings,
I am using Salat and Casbah to create a user collection in Mongodb, everything works great until I added a unique index on the email field. Now my insert returns a unique id with no actual record added in the DB for existing email addresses. I am new to scala and Casbah/Salat so I apologize if I am asking an obvious question.
here are my collection indexes
db.users.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "study_test.users"
},
{
"v" : 1,
"unique" : true,
"key" : {
"email" : 1
},
"name" : "users_email",
"ns" : "study_test.users"
}
]
and this is my dao object
object UserDao extends SalatDAO[UserModel, ObjectId](collection = MongoUtil.getCollection("study", "users")) {
val logger = LoggerFactory.getLogger(UserDao.getClass)
val dao = this
UserDao.collection.ensureIndex(DBObject("email" -> 1), "users_email", true)
RegisterJodaTimeConversionHelpers()
def create(userContract: UserContract): Option[ObjectId] = {
val userModel = UserConverter.toModel(userContract)
dao.insert(userModel)
}
}
I found what the problem was, I upgraded mongodb and casbah 2.10 but used MongoConnection to connect to mongoDB. I switched to connection using mongo client and all works as expected.
What do you mean by "Now my insert returns a unique id with no actual record added in the DB for existing email addresses." Can you specify an example?
Since you have a unique index, insert will fail for a new insert (or whatever the behaviour for scala/casbah is) for the same email id.