MongoDB java client's WriteConcern doesn't work - mongodb

I am a newbie to use MongoDB. I just imported the latest MongoDB java client via Maven:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.2.2</version>
</dependency>
And then I wrote a very simple program to test the insert operation.
//I use a replicaset
MongoClient mongoClient = new MongoClient(
Arrays.asList(new ServerAddress("10.12.16.136", 29017),
new ServerAddress("10.12.16.136", 29018),
new ServerAddress("10.12.16.136", 29019)));
//I just want to write and ignore any database errors. (This does not work)
mongoClient.setWriteConcern(WriteConcern.UNACKNOWLEDGED);
//Get database and collection
MongoDatabase database = mongoClient.getDatabase("test");
MongoCollection<Document> collection = database.getCollection("realtime");
//This does not work too.
collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED);
//Make a simple object to insert. I already have a document with the same _id in the database and I don't want to see the exception via the WriteConcern operation.
Document doc = Document("longitude", longitude)
.append("latitude", latitude)
.append("velocity", velocity)
.append("soc", soc)
.append("_id", 12345678);
//WriteConcern.UNACKNOWLEDGED doesn't work. An exception will be raised.
collection.insertOne(doc);
How can I do the right thing?

That's because collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED); generates a new MongoCollection object with a different write concern which you never use:
/**
* Create a new MongoCollection instance with a different write concern.
*
* #param writeConcern the new {#link com.mongodb.WriteConcern} for the collection
* #return a new MongoCollection instance with the different writeConcern
*/
MongoCollection withWriteConcern(WriteConcern writeConcern);
The following code:
MongoCollection<Document> dup = collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED);
...
dup.insertOne(doc);
should work, i.e. no error raised.
As for the MongoClient level write concern which is not propagated to the database:
public MongoDatabase getDatabase(final String databaseName) {
MongoClientOptions clientOptions = getMongoClientOptions();
return new MongoDatabaseImpl(databaseName, clientOptions.getCodecRegistry(), clientOptions.getReadPreference(),
clientOptions.getWriteConcern(), createOperationExecutor());
}
As you can see, the write concern is taken from MongoClientOptions ignoring the parameter value passed to mongoClient.setWriteConcern() method, which may be a bug.
So, to set a global write concern properly, you will have to create an instance of MongoClientOptions:
MongoClientOptions options = MongoClientOptions
.builder()
.writeConcern(WriteConcern.UNACKNOWLEDGED)
.build();
and pass it to the MongoClient constructor.

I had got this exception, when on empty collection was already present in MongoDB, and i was trying to create one more same collection by mistake, so when i deleted the existing collection and then did a post API, then it worked fine for me..
So better first drop your existing collection and then try to call any CRUD API..
if there is one Java entity with Collection ( name="STUDENT" ) , and you are again trying to create one collection with name student, this error comes

Related

MongoDB Change Stream for Azure CosmosDB MongoDB API

I have to use MongoDB Change Stream. The MongoDB is setup using CosmosDB MongoDB API. Wire compatibility is supported.
Somehow I cannot setup a watch. Here is the code I am using:
string connectionstring="my connection string";
var mongoClient = new MongoClient(connectionstring);
var database = mongoClient.GetDatabase("Events");
var collection = database.GetCollection<BsonDocument>("ACollection");
var options = new ChangeStreamOptions() { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup };
var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<BsonDocument>>().Match("{ operationType: 'insert' }");
var cursor = collection.Watch(pipeline, options).ToEnumerable();
This last last throws an exception
Unhandled exception. MongoDB.Driver.MongoCommandException: Command aggregate failed: Change stream must be followed by a match and then a project stage.
...
...
at MongoDB.Driver.MongoCollectionImpl`1.Watch[TResult](PipelineDefinition`2 pipeline, ChangeStreamOptions options, CancellationToken cancellationToken)
at CosmosChangeStream.Program.Main(String[] args) in Program.cs:line
I have also tried
cursor = collection.Watch();
This line is written like this in many getting started articles, but it throws another exception.
MongoDB.Driver.MongoCommandException: Command aggregate failed: fullDocument option must be "updateLookup"..
Obviously it is looking for projection. Wondering how so many examples have code that does not run. But this not my problem, my problem is to get an IEnumerable Change Stream for all inserts to one or all collections in a database, and be on my way.
I have validated my connection to the database and collection by reading a document.
Thanks to any one who looks at this
I was able to make it work with the help of this article:
https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/change-streams?tabs=csharp
This has the pipeline definition including match and projection staging.

Delete all documents in a collection with Springdata mongo Query

I want to implement a delete method which deletes all the documents in a collection. I am using mongo db with Spring Data.This could be done using db.myCollection.remove({}) in Mongo shell. But I want to write a method in my data access layer to do this.I am not using MongodbTemplate in my Dao class. I want to know how can I do this with Query.
Query query = new Query();
Could anybody please tell me how can I do it.
You can use MongoTemplate directly
mongoTemplate.remove(new Query(), collectionName);
Use MongoRepository's deleteAll(). Utilizes mongoTemplate behind the scene to call the remove method.
From calling method someRepository.deleteAll()
Drop collection may be efficient as other answer has noted. For that you will need to use MongoTemplate directly and call dropCollection with entity class or collection name.
You can drop the collection and create it again:
mongoTemplate.dropCollection("collectionName");
mongoTemplate.createCollection("collectionName");
You'd better drop the entire collection (if possible) than deleting all documents. For performance and allocation sake.
You can try something such as:
MongoClient mongoClient = new MongoClient(new ServerAddress("localhost", 27017));
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection collection = db.getCollection("test_collection");
collection.drop();
If you do want to delete all (I think), instead of:
collection.drop();
use:
Bson filter = new Document();
collection.deleteMany(filter);
Query is part of spring-data-mongodb, if you can't use a MongoTemplate, probably Query is irrelevant as well.
If you have considerable changes in schema, better is to drop the collection.
MongoTemplate.dropCollection(collectionName).
But the requirement is to delete all documents you have use
MongoTemplate.remove(new Query(), collectionName)or
CrudRepository.deleteAll()
If all collections are to be deleted, this could also be done:
mongoTemplate.collectionNames
.forEach { mongoTemplate.dropCollection(it) }

How to create a collection in MongoDB using SPRING data

Am using Spring-Data-Mongo to access do CRUD operations on my mongo database. I execute the below line
DB db = mongoTemplate.getDb()
When am in debug mode I can see that db._collections properties has 4 values (collections that I inserted). But when I query for
db.getCollectionNames()
I get zero collections back. Why is that? Same is also true when I do
db.getCollection("collectionName")
But I know the collections do exists because when I do something like
mongoTemplate.createCollection("collectionName");
I get an exception saying that collection already exists. Can anyone please explain what I might be missing
MongoTemplate provides a few methods for managing collections. The following example demonstrates some of the methods:
DBCollection collection = null;
if (!mongoTemplate.getCollectionNames().contains("collectionName")) {
collection = mongoTemplate.createCollection("collectionName");
}
mongoTemplate.dropCollection("collectionName");
In the above, getCollectionNames() returns a set of collection names and dropCollection() drops the collection.
Use MongoClient, MongoDatabase, and MongoIterable of com.mongodb.client and com.mongodb package.
MongoClient client = MongoClient(<host>, port);
MongoDatabase db = client.getDatabase(<Name of the database>);
MongoIterable<String> = db.listCollectionNames();
And now you can iterate over all the names of the collections.
Additionally, you even can use MongoCollection class to get the Document from the specified collection. The getCollection() will create collection if not present.
MongoCollection<Document> collection = db.getCollection(<Collection name>);

JMETER - MongoDB delete record sample script for jmeter

Can someone help me on groovy sample code for deleting a record from a MongoDB collection ? Thanks in advance.
Prior to removing an object your need to find one.
Full sample code (my expectation is that you're interested in the last line only, but just in case):
import com.mongodb.* // import all the mongodb.* stuff
import org.apache.jmeter.protocol.mongodb.config.MongoDBHolder;
DB db = MongoDBHolder.getDBFromSource("MongoDBSourceName", "DatabaseName");
DBCollection collection = db.getCollection("CollectionName");
BasicDBObject query = new BasicDBObject("name", "value"); // create DBObject holding the query
DBObject result = collection.findOne(query); // find the document
collection.remove(result); //delete the document
References:
DBCollection class JavaDoc (see remove() and findAndRemove() methods in particular)
How to Load Test MongoDB with JMeter

MongoDB Java Driver creating Database and Collection

i was testing how to create database and collection mongo java driver.
MongoClient client = new MongoClient("localhost",27017);
DB db = client.getDB("ow");
DBCollection collection = db.getCollection("documents");
collection.save(new BasicDBObject("_id",1));
collection.remove(new BasicDBObject("_id",1));
boolean result = db.collectionExists("documents");
assertTrue(result);
assertNotNull(collection);
client.close();
I would prefer to use createCollection method on the DB object, but found that it does not create database / collection unless the first document is inserted.
My question is is this understanding correct ? Is above code correct was of creating collection or database.
prefer to use createCollection method on the DB object, but found that it does not create database / collection unless the first
document is inserted.
MongoDB creates a collection implicitly when the first document is saved into a collection. The createCollection() method explicitly creates a collection only and only if an options object is passed to it as an argument.
Now this makes sense. The options parameter can take in one or more arguments to decide the characteristics of the collection we want to create such as capped,autoIndexId,size,usePowerOf2Sizes,max no. of documents.
If we do not specify any of these options, the default behavior would take precedence, i.e create a collection lazily whenever the first insert is made, with default settings.
So if we want a collection whose characteristics we are going to define, then we can pass these characteristics as a DBObject to the createCollections() method and our collection would be created. Below is an example of how to pass the options.
BasicDBObject options = new BasicDBObject();
options.put("size", 12121212);
db.createCollection("hello", options);
Is above code correct was of creating collection or database.
Yes. It allows mongodb to apply the default configuration for your collection. Unless you want to set the
max,size,autoIndexId,capped,usePowerOf2Sizes properties for your new collection, this is fine.
Refer: http://docs.mongodb.org/manual/reference/method/db.createCollection/