How to update field type in a document using Java MongoDB Reactive driver? - mongodb

I have a document in MongoDB collection:
{
"fOne": "strValue",
"fTwo": {
"nestedFArray": [
{
"dateF": "2010-01-02T13:00:01"
},
{
"dateF": "2010-01-02T13:00:01"
}
],
"nestedFObject": {
"anotherDateF": "2010-01-02T13:00:01"
}
}
}
fields fTwo.nestedFArray[0].dateF, fTwo.nestedFArray[1].dateF, fTwo.nestedFObject.anotherDateF stored as a string type; How to replace types of this field with DateTime type when I have a json paths for fields using java mongo reactive driver?
$.fTwo.nestedFArray[0].dateF
$.fTwo.nestedFArray[1].dateF
$.fTwo.nestedFObject.anotherDateF

The query is an aggregation which converts the string date values to Date values. The result list from the aggregation is iterated and the modified documents are updated in a for-loop. Note the code assumes a collection with multiple input documents.
The Java Code:
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import com.mongodb.reactivestreams.client.MongoCollection;
import com.mongodb.reactivestreams.client.MongoDatabase;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.WriteModel;
import com.mongodb.bulk.BulkWriteResult;
import java.util.*;
public class MongoReact {
public static void main(String[] args)
throws Throwable {
MongoClient mongoClient = MongoClients.create();
MongoDatabase db = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = db.getCollection("test");
List<Bson> pipeline =
Arrays.asList(
new Document("$project",
new Document("fTwo.nestedFObject.anotherDateF",
new Document("$dateFromString",
new Document("dateString", "$fTwo.nestedFObject.anotherDateF")
)
)
.append("fTwo.nestedFArray",
new Document("$map",
new Document("input", "$fTwo.nestedFArray")
.append("as", "e")
.append("in",
new Document("dateF",
new Document("$dateFromString",
new Document("dateString", "$$e.dateF")
)
)
)
)
)
)
);
SubscriberHelpers.ObservableSubscriber<Document> querySubscriber =
new SubscriberHelpers.ObservableSubscriber<Document>();
collection.aggregate(pipeline).subscribe(querySubscriber);
querySubscriber.await();
List<Document> resultDocs = querySubscriber.getReceived();
List<WriteModel<Document>> updates = new ArrayList<>();
for (Document doc : resultDocs) {
ObjectId id = (ObjectId) doc.get("_id");
Document f2Doc = (Document) doc.get("fTwo");
updates.add(new UpdateOneModel<Document>(
new Document("_id", id),
new Document("$set", new Document("fTwo", f2Doc))
));
}
SubscriberHelpers.PrintSubscriber<BulkWriteResult> updateSubscriber =
new SubscriberHelpers.PrintSubscriber<BulkWriteResult>("Bulk write results: %s");
collection.bulkWrite(updates).subscribe(updateSubscriber);
updateSubscriber.await();
mongoClient.close();
}
}
NOTES:
The SubscriberHelpers is a utility class used in the above code. I have used it as shown in the Quick Tour (with examples) section of the Reactive Streams Java Driver page.
The source code for the SubscriberHelpers.java can be found at: mongo-java-driver-reactivestreams/examples/tour/src/main/tour/. The usage of the code and examples source code is also there - you can compile and use it.
I have used MongoDB server 4.0, Java SE 8, MongoDB Reactive Streams driver 1.10.0 and mongodb-driver-async 3.9.0 to work with the above code.

Related

How to fetch mongo db data and pass in jmeter request

I have one post call that response is like this.
{
"status":0,
"message":"Prescription Created",
"jsonResponse":{},
"cid":"C5975K",
"pid":"Rx5975K-175A",
"prescriptionSource":"GO_RX_CTO",
"imageStatus":[]
}
By taking this pid , I have to do the query for the one more record. For example:
db.order.find({"pid":"Rx5975K-175A"})
and the result of this query should pass in one more jmeter request.
I have used MongoDB Script (DEPRECATED) .. But this wont work as its deprecated ..
Tried with JSR223 Sampler, but its not working in new jmeter 3.2
import com.mongodb.*
import com.mongodb.BasicDBObject
MongoCredential coreCredential = MongoCredential.createCredential("${mongodb_user}", "${mongodb_database}", "${mongodb_password}".toCharArray());
MongoClient coreMongoClient = new MongoClient(new ServerAddress("${mongodb_server}", 13017), Arrays.asList(coreCredential));
DB coreDB = coreMongoClient.getDB("${mongodb_database}");
DBCollection coll = coreDB.getCollection("order");
coll.find();
You have to find your result based on "pid" and you are nowhere passing it. After finding you collection you need to create a query and searching using that query.
import com.mongodb.*
import com.mongodb.BasicDBObject
MongoCredential coreCredential = MongoCredential.createCredential("${mongodb_user}", "${mongodb_database}", "${mongodb_password}".toCharArray());
MongoClient coreMongoClient = new MongoClient(new ServerAddress("${mongodb_server}", 13017), Arrays.asList(coreCredential));
DB coreDB = coreMongoClient.getDB("${mongodb_database}");
DBCollection coll = coreDB.getCollection("order");
BasicDBObject query = new BasicDBObject();
query.put("pid", "Rx5975K-175A");
DBObject getData= coll.findOne(query);
and this will give you the desire result

How to add data in right collection in pymongo?

I want to add data in right collection considering by name. The code below is defining well. collection(db,name) returns the name of collection. But when I want to save the collection name via rightCollection = collections(db, name) and inserting it as db.rightCollection.insert({"1" : "Righ collection"}). Pymongo is creating the collection under name rightCollection not Peter. I want to insert data in Peter. Why is it so? Can I resolve it?
from pymongo import MongoClient
def collections(db,name):
if(name is 'Peter'):
return db.Peter
client = MongoClient()
db = client.myDB
name="Peter"
rightCollection = collections(db, name)
db.rightCollection.insert({"1" : "Righ collection"})
Using pymongo 3.2.2, you don't need the collections function, you can just use the collection name directly:
from pymongo import MongoClient
client = MongoClient()
db = client.myDB
db.Peter.insert_one({'1': 'Right collection'})
That should insert the document {'1': 'Right collection} into collection Peter under database myDB. To verify that the data is inserted correctly, you can use the mongo shell:
> use myDB
> db.Peter.find()
{ "_id": ObjectId("57df7a4f98e914c98d540992"), "1": "Right collection" }
Or, if you need the name Peter to be defined in a variable, you can do:
from pymongo import MongoClient
client = MongoClient()
db = client.myDB
coll_name = 'Peter'
db[coll_name].insert_one({'1': 'Right collection'})

Copying a mongo collection using Java Driver

I want to copy the contents from one collection to another.
in mongod this can be done:
db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} )
Using Java Mongo Driver, I try:
DB db = mongoClient.getDB("mydb")
CommandResult result = db.command("db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} )")
But I get:
result = [serverUsed:localhost:27017, ok:0.0, errmsg:no such cmd: db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} ), code:59, bad cmd:[db.tempMongoItem.find().forEach( function(x){db.mongoItem.insert(x)} ):true]]
Any ideas?
You need to emulate the same thing JS is doing in Java, which means getting a cursor and iterating over it, inserting each document into new collection.
Something like this (coll is current, coll2 is new collection):
DBCursor cursor = coll.find();
try {
while(cursor.hasNext()) {
coll2.insert(cursor.next());
}
} finally {
cursor.close();
}
Both coll and coll2 are assumed to be DBCollection type.
Since it appears you are copying within the same DB, there is another way to do this if you are using 2.6 MongoDB using aggregation framework $out stage:
db.collection.aggregate({"$out":"newCollection"});
Note that this is limited to outputting into the same DB that original collection is in.
The following JAVA code will copy the collection from source to destination for a given database name (using mongodb-driver 3.0.4)
/** Clone a collection.
*
* #param fromCollectionName - The name of collection to be cloned
* #param toCollectionName - The name of the cloned collection
* #param dbName - The name of the database
*/
public void cloneCollection(String fromCollectionName, String toCollectionName, String dbName) throws MongoException {
MongoCollection toCol = this.getCollection(toCollectionName, dbName);
if (toCol != null) {
throw new MongoException("The destination collection already exists.");
}
List<Document> ops = new ArrayList<>();
ops.add(new Document("$out",toCollectionName));
MongoCollection sourceCollection = this.getCollection(fromCollectionName, dbName);
sourceCollection.aggregate(ops);
}
public MongoCollection getCollection(String collection, String dbName) {
MongoClient mongo = new MongoClient(new ServerAddress("localhost", Integer.parseInt(port)));
MongoDatabase database = mongo.getDatabase(dbName);
return curdb.getCollection(collection);
}
Please note that this will not copy over the indices that you have created in source collection. You will have to copy the indices seperately
Following up on Asya's response, you can use Java 8 Lambda functions to do:
collSource.find().forEach((Block<Document>) collTarget::insertOne);

Insert DBObject into MongoDB using Spring Data

I tried to insert the following DBObject into MongoDB using Spring Data:
BasicDBObject document = new BasicDBObject();
document.put("country", "us");
document.put("city", "NY");
mongoTemplate.insert(document);
where mongoTemplate is my Spring template (org.springframework.data.mongodb.core.MongoTemplate).
When executing, I get:
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: No Persitent Entity information found for the class com.mongodb.BasicDBObject
at org.springframework.data.mongodb.core.MongoTemplate.determineCollectionName(MongoTemplate.java:1747)
at org.springframework.data.mongodb.core.MongoTemplate.determineEntityCollectionName(MongoTemplate.java:1732)
at org.springframework.data.mongodb.core.MongoTemplate.insert(MongoTemplate.java:658)
My JSON would be dynamic at the end. So any idea how to provide these entity information dynamically ?
Or is there another way to insert raw JSON into Mongodb through Spring Data ?
You are confusing spring-data with normal mongo persistence using the java driver.
If you want to persist data to mongoDB directly using the java driver then you would use the BasicDBObject like you have shown except that you would not use the mongoTemaplate class to persist but rather the MongoClient class. So it would look like this:
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
DB db = mongoClient.getDB( "mydb" );
BasicDBObject o = new BasicDBObject();
o.set......
coll.insert(o);
But if you are trying to persist a document using spring-data, then you need to create a java class to represent your document (eg: Person) and annotate this class with #Document(collection="person") and then use the mongoTemplate (which is a spring-data specific class to persist this entity. This is very similar to using JPA/hibernate.
So it would look something like this
#Document(collection="person")
public class Person {
private String fisrtName;
....
Relevant getters and setters
}
And then the persistence
Person p = new Person();
p.setFirstName("foo");
p.setLastName("bar");
....
mongoTemplate.save(p);
Another way to do this is to directly access the DBCollection object via the MongoTemplate:
DBObject company = new BasicDBObject();
...
DBCollection collection = mongoTemplate.getCollection("company");
collection.insert(company);
Another way to do it
Import statements
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
Member Variables
#Autowired MongoTemplate mongoTemplate;
MongoCollection<Document> collection;
#PostConstruct
public void init(){
collection = mongoTemplate.getCollection("company");
}
And then, the method
public void insertRawData(){
Document company = new Document(new HashMap()); // If you have to insert a hashMap
// otherwise you can add one-by-one using company.put("foo","bar")
collection.insertOne(company);
}

using findAndModify in mongodb using grails gorm

I need to use findAndModify in my application with grails and mongoDB.
I used this code :
public static String getNextId(DB db, String seq_name) {
String sequence_collection = "seq"; // the name of the sequence collection
String sequence_field = "seq"; // the name of the field which holds the sequence
DBCollection seq = db.getCollection(sequence_collection); // get the collection (this will create it if needed)
// this object represents your "query", its analogous to a WHERE clause in SQL
DBObject query = new BasicDBObject();
query.put("_id", seq_name); // where _id = the input sequence name
// this object represents the "update" or the SET blah=blah in SQL
DBObject change = new BasicDBObject(sequence_field, 1);
DBObject update = new BasicDBObject("$inc", change); // the $inc here is a mongodb command for increment
// Atomically updates the sequence field and returns the value for you
DBObject res = seq.findAndModify(query, new BasicDBObject(), new BasicDBObject(), false, update, true, true);
return res.get(sequence_field).toString();
}
and it work successful. But now I want use findAndModify without native mongodb object, and with using GORM.
Is there any solution for this work?
There is not way to accomplish this without native API, you can however write your code a bit more compact like this:
def collection = Seq.collection
collection.findAndModify([_id: seq_name ], [ "\$inc": [seq:1] ])
Config your DataSource.groovy with db configurations.
Then define a Domain class:
Class Seq{
int seq
}
And use dynamic finder in a sevice:
Class SeqService {
String findAndModify(String seq_name) {
def seqInstance = Seq.get(seq_name)
if(seqInstance){
seqInstance.seq ++
seqInstance.save()
return seqInstance.seq.toString()
}
return '' //instance not found
}
}
Then make a call when you need that action:
def seqService
def id
.......
def result = seqService.findAndModify(id)
....