Cannot get _id of MongoDB object with java driver - java

I'm inserting objects into MongoDB without specifying the _ids, because I want it to create them automatically. The problem is that at a certain point of the program I need to retrieve the _ids, but I can't get them. The code I use is the following:
List<DBObject> objs=collection.find(filter).toArray();
BDObject obj=objs.get(0);
String id=obj.get("_id");
//now id is something like 2d938830-2732-44fd-84b0-aa56b95c5df0
Eventually the id variable contains a GUID, but it's different from the one I see in RoboMongo, so it's wrong. What I see in RoboMongo is something like:
"_id": LUUID("cada0d4f-a72d-47ad-8ea8-239c3e5795dd")

Related

MongoWriteException when inserting into Mongodb with composite custom _id

I have a MongoDB remote server that I am using.
My KEY is a custom object that has other nested objects in it.
Simple inserting works fine, although if I try to run
collection.replaceOne(eq("_id", KEY), document, new UpdateOptions().upsert(true));
I get com.mongodb.MongoWriteException: After applying the update, the (immutable) field '_id' was found to have been altered to _id: .......
If I have only have primitives in the key it works fine. Of course the value of the KEY is not changed (traced all the way down).
Is this a Mongo Java Driver bug with the ReplaceOne function?
As it turns out for Mongo filters, the order of json properties matter. With debugging it is possible to see what the actual orders of the properties in the filters are and then you can set your model properties order with #JsonPropertyOrder("att1", att2") so they match in order.
It was confirmed by a member of Mongo team.
Mongo ticket-> https://jira.mongodb.org/browse/JAVA-3392

Firestore SetOptions.mergeFields doesn't store field

So I have this function to store user into Firestore after he successfully registers.
//User class
id: String
email: String?
displayName: String?
photoUrl: String?
//updateOrInsertUser method
collectionReference.document(user.id)
.set(
user,
SetOptions.mergeFields(
FIELD_photoUrl,
FIELD_email,
FIELD_displayName
)
)
But when I call updateOrInsertUser(user) only fields that are in SetOptions are stored in Firestore, therefore id is not stored.
Is there a simple way to override old values defined in SetOptions if the document already exists and if there is not doc store everything?
I don't want to fetch old document before updating :(
No I don't want to add id into SetOptions(imagine other use cases when you don't want to override field that already exists in database)
But when I call updateOrInsertUser(user) only fields that are in SetOptions are stored in firestore, therefore id is not stored.
This is the normal behaviour since you aren't passing the id to the SetOptions's mergeFields() method.
Is there a simple way to override old values defined in SetOptions if the document already exists and if there is not doc store everything? I don't want to fetch old document before updating :(
The simplest way would be to get the "old" document, change its values and write it back to the database but there is also another approach that can help you change the values within a document and this is by using a Map along with a update() method call. In code, might look like this:
Map<String, Object> user = new HashMap<>();
user.put("photoUrl", FIELD_photoUrl);
user.put("email", FIELD_email);
user.put("displayName", FIELD_displayName);
userDocumentReference.update(user);

Using MongoDB 3.4 to load and save userdata

How can I find a document and retrieve it if found, but insert and retrieve it if not found in one command?
I have an outline for the formats I wish my documents to look like for a user's data. Here is what it looks like
{
"username": "HeyAwesomePeople",
"uuid": "0f91ede5-54ed-495c-aa8c-d87bf405d2bb",
"global": {},
"servers": {}
}
When a user first logs in, I want to store the first two values of data (username and uuid) and create those empty values (global and servers. Both those global and servers will later on have more information filled into them, but for now they can be blank). But I also don't want to override any data if it already exists for the user.
I would normally use the insertOne or updateOne calls to the collection and then use the upsert (new UpdateOptions().upsert(true)) option to insert if it isn't found but in this case I also need to retrieve the user's document aswell.
So in a case in which the user isn't found in the database, I need to insert the outlined data into the database and return the document saved. In a case where the user is found in the database, I need to just return the document from the database.
How would I go about doing this? I am using the latest version of Mongo which has deprecated the old BasicDBObject types, so I can't find many places online that use the new 'Document' type. Also, I am using the Async driver for java and would like to keep the calls to the minimum.
How can I find a document and retrieve it if found, but insert and retrieve it if not found in one command?
You can use findOneAndUpdate() method to find and update/upsert.
The MongoDB Java driver exposes the same method name findOneAndUpdate(). For example:
// Example callback method for Async
SingleResultCallback<Document> printDocument = new SingleResultCallback<Document>() {
#Override
public void onResult(final Document document, final Throwable t) {
System.out.println(document.toJson());
}
};
Document userdata = new Document("username","HeyAwesomePeople")
.append("uuid", "0f91ede5")
.append("global", new Document())
.append("servers", new Document());
collection.findOneAndUpdate(userdata,
new Document("$set", userdata),
new FindOneAndUpdateOptions()
.upsert(true)
.returnDocument(ReturnDocument.AFTER),
printDocument);
The query above will try to find a document matching userdata; if found set it to the same value as userdata. If not found, the upsert boolean flag will insert it into the collection. The returnDocument option is to return the document after the action is performed.
The upsert and returnDocument flags are part of FindOneAndUpdateOptions
See also MongoDB Async Java Driver v3.4 for tutorials/examples. The above snippet was tested with current version of MongoDB v3.4.x.

Retrieving full objects from a query done via Bolt protocol

In Neo4J, I want to use the bolt protocol.
I installed the 3.1 version of Neo4J.
I my Java project, that already works well with normal HTTP Rest API of Neo4J, I integrate with Maven the needed drivers and achieve to perform request with BOLT.
The problem is everywhere you make a search about bolt they give example like this one :
MATCH (a:Product) return a.name
But I don't want the name, I want all the data of all product, what ever i know or not before what are these columns, like here:
MATCH (a:Product) return * --> here I retrieve only the ids of nodes
I found there https://github.com/neo4j-contrib/neo4j-jdbc/tree/master/neo4j-jdbc-bolt we can "flatten" the result but it seems to not work or I didn't understand how it works:
GraphDatabase.driver( "bolt://localhost:7687/?flatten=-1", AuthTokens.basic( "neo4j", "......." ) );
I put the ?flatten=-1 at the end of my connection address... but that changed nothing.
Anyone can help? Or confirm it's not possible or not working ?
Thanks
Ok I understood my error, I didn’t dig enough in the object returned. So used to have a JSON formatted response, I didn’t see that I have to search in the StatementResult object to find the wanted object with its properties. In fact Eclipse in the “expressions” shows “in fly” only the ids, but inside the object data are there.
Record oneRecord = rs.next();
String src = oneRecord.get("m").get("source");
That way I can reconstruct my object

How can I bulk update my mongo data to add a fixed level?

I recently changed a POJO from having all its typed properties to something free in a typed JSONObject field called content.
The problem is that all old documents map to the old POJO version, so they are stored like this:
{"_id":"ObjectId(value)","field1":"value1","field2":"value2"}
Can I update all fields via a single mongo command so I can wrap all the content, except the id, so the result would be something like this:
{"_id":"ObjectId(value)","content":{"field1":"value1","field2":"value2"}}
?
Or should I program a simple program that does it one by one? (as in iterating all values sort of manually adding the new content level)
Unfortunately, there are no MongoDB commands that will allow you to restructure a document in this way. You'll need to write a program to fetch all of your documents one by one, update the structure, and then send the updated structure back to MongoDB.
Often the best way to do this is to write the modified documents to a new collection, and then drop the old collection when you're done.
I solved it creating a .js file to execute via mongo shell.
mongo myDb fixresults.js
The file is as follows:
for( var c = db.results.find(); c.hasNext(); ) {
var full = c.next();
var anon = db.results.findOne({"_id":full._id},{"_id":0});
var n = {"_id":full._id,"content":anon};
db.results.temp.insert(n);
}
This will insert the transformed value into the .temp collection, which you can rename later to replace the original.

Categories