Cannot insert document into collection - java

I have the following method :
MongoCollection<Document> collection;
...
Document query = new Document();
query.put("uuid", uuid);
query.put("gems", "$exists");
Document document = collection.find(query).first();
if(document == null) {
System.out.println("Not found");
document = new Document();
document.put("uuid", uuid);
document.put("gems", 0L);
collection.insertOne(document);
}
Now, the collection is there, I checked in Mongo, but for some reason the document is never inserted.
I run:
db.(collection).find()
And get no output.
The document is never found, I don't know if my query is correct, but the document is never inserted. This is done with a clean install of MongoDB running on localhost. MongoDB shows as connected and no errors are thrown.
Am I missing something?

This code seems to work, it fixes the insert and finding method:
Document document = collection.find(Filters.eq("uuid", uuid)).first();
if (document == null) {
document = new Document("uuid", uuid);
document.put("gems", 0L);
collection.insertOne(document);
}

Related

MongoDB "Invalid BSON Field Name"

I know that there's probably a better way to do this however I'm completely stumped. I'm writing a Discord bot in which a user is able to add points to other users, however I can't figure out how to replace a user's "points". My code is as follows:
BasicDBObject cursor = new BasicDBObject();
cursor.put(user.getAsMember().getId(), getMongoPoints(user.getAsMember()));
if(cursor.containsKey(user.getAsMember().getId())) {
Document old = new Document(user.getAsMember().getId(), getMongoPoints(user.getAsMember()));
Document doc = new Document(user.getAsMember().getId(), getMongoPoints(user.getAsMember()) + Integer.parseInt(amount.getAsString()));
collection.findOneAndUpdate(old, doc);
}
My getMongoPoints function:
public static int getMongoPoints(Member m) {
ConnectionString connectionString = new ConnectionString("database");
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase database = mongoClient.getDatabase("SRU");
MongoCollection<Document> collection = database.getCollection("points");
DistinctIterable<Integer> docs = collection.distinct(m.getId(), Integer.class);
MongoCursor<Integer> result = docs.iterator();
return result.next();
}
I've tried findOneAndReplace, however that simply makes a new entry without deleting the old one. The error I receive is: Invalid BSON field name 262014495440896000
Everything else works, include writing to the database itself which is why I'm stumped. Any help would be greatly appreciated and I apologize if this is written poorly.
BSON field names must be string. From the spec:
Zero or more modified UTF-8 encoded characters followed by '\x00'. The (byte*) MUST NOT contain '\x00', hence it is not full UTF-8.
To use 262014495440896000 as a field name, convert it to string first.

Specific field of a document in MongoDb to Java Object

I want to select a specific field of a document in Mongodb collection and convert it to java object.
My document is like this:
{
"Name":"Ben",
"template":"A fingerprint template which I extracted"
}
So I wish select this "template field"
My sample code is below:
List<Document> documents = (List<Document>) collection.find().into(new ArrayList<Document>());
for (Document document : documents) {
Document doc = documents.get(document);
FingerprintTemplate template = (FingerprintTemplate) doc.get("template");
And the error is:
java: incompatible types: org.bson.Document cannot be converted to int
Any idea or any suggestions please!!
You can query if the field exists:
collection.find("template": { $exists: true, $ne: null } });
For the mapping part, you can have a look at objectMapper to map directly to a java object: https://www.baeldung.com/jackson-object-mapper-tutorial
Your error is still that you have a Document and Java is expecting an int.
Try this :
BasicDBObject query = new BasicDBObject();
BasicDBObject whereQuery = new BasicDBObject();
basicDBObject.put("template",1);
DBCursor cursor = collection.find(query,whereQuery);
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
This would print the documents that have template but to convert to Object you would need some JSON Object mapper maybe jackson

Trying to update a document using MongoDB Java Driver

Thank you
I just want to thank you for clicking on this question! I've tried my best to make this as thorough as possible.
but still, feel free to let me know if you need to clarify anything further!
if you think the question is too long. you can just read the third & fourth part and post your own solution down here!
Setup
Mongodb Java driver: org.mongodb:mongo-java-driver:3.11.0-rc0
What I want to do
find a specific document with a specific "name" field.
then update the other field or the whole document.
Example Document
// the document that I am trying to find in db
{
"_id":"5de6af7cfa42833bd9849477",
"name":"Richard Koba",
"skills":[]
}
// the document that I have
{
"name":"Richard Koba",
"skills":[jump, dance, sing]
}
// final result in db
{
"_id":"5de6af7cfa42833bd9849477",
"name":"Richard Koba",
"skills":[jump, dance, sing]
}
What I am doing now
// finding a document with same "name" field as input doc and update it with doc
public MongoCollection updateDocument(Document doc, String colName) {
MongoCollection collection;
// make sure collection exist
try {
collection = connectCollection(colName); // returns MongoCollection Obj
} catch (CollectionNotFoundException e) {
MessageHandler.errorMessage(e.getMessage());
return null;
}
// trying to find the document.
if (collection.find(eq("name", doc.get("name"))).first() == null) {
// if document not found, insert a new one
collection.insertOne(doc);
} else {
// if the document found, replace/update it with the one I have
collection.replaceOne(eq("name", doc.get("name")), doc);
}
return collection;
}
What I found about my false solution
collection.find(eq("name", doc.get("name"))).first() never returns null.
Java only tells me it returns an Object. MongoDB Documentation tells me it is a TResult, which point back to MongoIterable<TResult>. I am stuck here.
the code outcome is that none of the documents is inserted/updated in the end.
Reference
https://mongodb.github.io/mongo-java-driver/3.11/javadoc/com/mongodb/client/MongoIterable.html#first()
I tried some code and this works fine. This is not much different from your code.
Created a document from mongo shell:
MongoDB Enterprise > db.users.findOne()
{
"_id" : "5de6af7cfa42833bd9849477",
"name" : "Richard Koba",
"skills" : [ ]
}
My Java Code:
// Test input documents
private Document doc1 = new Document()
.append("name", "Richard Koba")
.append("skills", Arrays.asList("jump", "dance", "sing"));
private Document doc2 = new Document()
.append("name", "Richard K")
.append("skills", Arrays.asList("sings"));
When doc1 is passed to the following method the result is: "### Doc FOUND". And, with doc2 the result is "### Doc NOT found".
private void checkDocument(Document doc) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost/");
MongoDatabase database = mongoClient.getDatabase("javadb");
MongoCollection<Document> collection = database.getCollection("users");
if (collection.find(eq("name", doc.get("name"))).first() == null) {
System.out.println("### Doc NOT found");
}
else {
System.out.println("### Doc FOUND");
}
}
I also tried this, with the same results.
Document d = collection.find(eq("name", doc.get("name"))).first();
if (d == null) { // ... }
I also tried this; works fine too.
if (collection.find(queryFilter).iterator().tryNext() == null) { // ... }
I think there might be some other issue with your code or the database / collection. Some debugging and testing with new data might reveal the real issue.
Did you check if the document already exists in the collection, from mongo shell or Compass tools?
Are you using the right database and collection names?
After each test run are you verifying the data in the database if it is updated / inserted?
collection.find(eq("name", doc.get("name"))).first() never returns
null.
With the code I posted above, the find query did return null when the users collection was empty.
collection.find() return an array of documents. What you actually want here is collection.findOneAndUpdate()
After you get a TDoucment object from findOneAndUpdate, you can use a ObjectMapper e.g.jackson to map it back to a java object

How to check if document exists in collection using mongo Java driver 3.0+

Using the new 3.0+ java driver from mongo what is the best way to check if a document exists in a collection.
I have looked at here and tried to do something similar. I have only gotten as far as this:
FindIterable<Document> iterable = collection.find(eq("code", "abcdefg")).projection(Projections.include("_id")).limit(1);
This returns a FindIterable but how do you check it has found anything at all ? If you can please provide a code example.
I did try:
if (!iterable.first().isEmpty()){System.out.println(" RESILT IS FOUND ");}else{System.out.println(" RESULT IS NOT FOUND ");}
but when the query returns nothing it dies with the following error:
Exception in thread "main" java.lang.NullPointerException
at com.oss.niagaramqtt.MongoLib.exists(MongoLib.java:58)
at com.oss.niagaramqtt.MongoLib.<init>(MongoLib.java:47)
at com.oss.niagaramqtt.startup.main(startup.java:24)
Indeed is this the correct approach overall for checking the existence of a document?
EDIT:
This could be the answer please confirm:
MongoCursor<Document> iterable = collection.find(eq("code", "abcdefg")).projection(Projections.include("_id")).limit(1).iterator();
if (iterable.hasNext()){System.out.println(" RESILT IS FOUND ");}else{System.out.println(" RESULT IS NOT FOUND ");}
Your way is good if you need to load this document in case it exists. If you don't need to load it then you can use MongoCollection.count method like:
long count = collection.count(new BsonDocument("code", new BsonString("abcdefg")));
if (count > 0){System.out.println(" RESILT IS FOUND ");}else{System.out.println(" RESULT IS NOT FOUND ");}
[Update] In case data is stored on a sharded cluster, db.collection.count() can result in an inaccurate count if orphaned documents exist or if a chunk migration is in progress. So it's safer to use aggregate function instead:
Iterator<Document> it = collection.aggregate(Arrays.asList(
new Document("$match", new Document("code", "abcdefg")),
new Document("$group", new Document("_id", null).append("count",
new Document("$sum", 1))))).iterator();
int count = it.hasNext() ? (Integer)it.next().get("count") : 0;
See http://docs.mongodb.org/manual/reference/sql-aggregation-comparison/ for more details.
Please check this count operation at java API 3.0 in a collection.
You can basically do:
MongoClient mongoClient2 = new MongoClient("localhost", 27017);
long count = mongoClient2.getDatabase("mongoBase")
.getCollection("collection")
.count(new Document("code", "abcdefg"));
if(count>0){
//exists
}
you will find great examples here:
https://github.com/mongodb/mongo-java-driver/tree/8866de115d45ea73a39da9360159d3fbb6390dd9/driver/src/examples/tour
There's several ways how to check if document exists in mongodb collection. For example,
1) Using method count():
long found = database.getCollection("mainCollection").count(new Document("title", title).append("url", url));
if (found == 0) {
collection.insertOne(new Document("title", title).append("url", url));
}
2) Using FindIterable:
FindIterable<Document> found = database.getCollection("mainCollection").find(new Document("title", title).append("url", url));
if (found.first() == null) {
collection.insertOne(new Document("title", title).append("url", url));
}
3) Using Document:
Document found = database.getCollection("mainCollection").find(new Document("title", title).append("url", url)).first()
if (found == null) {
collection.insertOne(new Document("title", title).append("url", url));
}
Just to add to the answers already here, I have been doing this in java:
if (entryRepository.exists(Example.of(entry))) {
log.error(String.format("Entry exists already"));
return true;
}

How do i do a Save operation on a MongoDB collection using the Java driver?

I just switch over from Python, and need to continue my work with a MongoDB database. One particular task is to save an incoming document (in this case, a tweet) into a collection for archiving. A tweet could comes in multiple times, so I prefer to use save() over insert() since the former do not raise an error if the document already exists in the collection. But it seems the Java driver for MongoDB does not support the save operation. Am I missing something?
EDIT: for reference, i'm using this library 'org.mongodb:mongodb-driver:3.0.2'
Example code:
MongoCollection<Document> tweets = db.getCollection("tweets");
...
Document tweet = (Document) currentDocument.get("tweet");
tweets.insertOne(tweet);
The last line raise this error when the tweet already exists:
Exception in thread "main" com.mongodb.MongoWriteException: insertDocument :: caused by :: 11000 E11000 duplicate key error index: db.tweets.$_id_ dup key: { : ObjectId('55a403b87f030345e84747eb') }
Using the 3.x MongoDB Java driver you can use MongoCollection#replaceOne(Document, Document, UpdateOptions) like this:
MongoClient mongoClient = ...
MongoDatabase database = mongoClient.getDatabase("myDB");
MongoCollection<Document> tweets = db.getCollection("tweets");
...
Document tweet = (Document) currentDocument.get("tweet");
tweets.replaceOne(tweet, tweet, new UpdateOptions().upsert(true));
This will avoid the duplicate key error. However, this is not exactly the same as using DBCollection#save(DBObject), since it uses the whole Document as filter instead of just the _id field. To mirror the old save method, you would have to write something like this:
public static void save(MongoCollection<Document> collection, Document document) {
Object id = document.get("_id");
if (id == null) {
collection.insertOne(document);
} else {
collection.replaceOne(eq("_id", id), document, new UpdateOptions().upsert(true));
}
}

Categories