I have a Json document in MongoDB collection that I would like to query based on _id.
{
"_id": {
"$oid": "102e8484f2caba7e805dc334"
},
"customerName": "TESLA",
"customerInfo": {
"name": "Elon",
},
"createdDate": {
"$date": "2021-02-19"
},
"modifiedDate": {
"$date": "2021-02-18T15:19:00.586Z"
},
"status": "DRAFT",
}
Now I have a working code with which if I query any other json key which is not system generated (say status or customerInfo.name), I am able to get the expected results.
But all trials that I did with _id or $date, did not work. I tried looking for answers in multiple posts but none of them worked. These are search options I tried before asking this question here:
import static com.mongodb.client.model.Filters.eq;
// above import used below.
MongoCursor<Document> cursor = collection.find(eq(key, value)).iterator();
where
key="_id.$oid"
value= byID (passed as say "123123121"
eq("_id.$oid", byID)
eq("_id.oid", byID)
eq("_id", byID)
eq("oid", byID)
eq("oid", ObjectId(byID)) - this gives compile errors.
Any help is much appreciated!
Found this answer on Slack (which I found to be working - tested Okay): How to query documents using "_id" field in Java mongodb driver?
by #bogolyandras with heading "For those who are seeking a more up to date method, especially with 3.4:"
Related
I am quite new to Spring Boot and MongoDB. I am trying to update the availability for a specific user within the user array. The issue is that I am trying to find a specific username for example: "Mark" and update that entry only. However, it could be under any index of the array, and I'm not quite sure how write that in the query statement.
The structure of my data in mongoDB:
{
"name": "test meeting",
"url": "temporary_url",
"timezone": "pacific",
"startTime": 8,
"endTime": 21,
"users": [
{
"username": "Mark",
"password": "Caddy",
"availability": { << TRYING TO UPDATE THIS
//array of objects
}
},
{
"username": "Bill",
"password": "Bobby",
"availability": {
//array of objects
}
}
],
"_class": "com.dcproduction.meetapp.classes.Meeting"
}
Below is my attempt to make it work. It works if I substitute an index for [WHAT GOES HERE] such as '0', but the point of this query is that I wouldn't normally know which index the name would fall under:
Query query = new Query();
query.addCriteria(
new Criteria().andOperator(
Criteria.where("name").is("test meeting"),
Criteria.where("users.[WHAT GOES HERE?]username").is("Mark")));
Update testUpdate = new Update();
testUpdate.set("users[WHAT GOES HERE].availability", some_data);
UpdateResult updateResult = mongoTemplate.updateFirst(query, testUpdate, Meeting.class);
Any help would be appreciated, thanks!
You could use identifiers as mentioned here: https://www.mongodb.com/docs/manual/reference/operator/update/positional-filtered/
which would be of the form:
query.addCriteria(
Criteria.where("users._username").is("Mark")
);
update.set("users.$[selector].availability", some_data)
.filterArray(Criteria.where("selector._username").is("Mark"));
Im trying to make this operation in java:
db.product.aggregate([{
$match: { gtin: { $in: ["7890203", "7890204" ]}}}])
.group({
_id: "$gtin",
status: {$last: "$status"},
createdDate: {$last: "$createdDate"}
})
This return only the last document for given gtins. (Thats my goal).
The java code:
Criteria criteria = Criteria.where("gtin").in(gtinList);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.group("_id", "gtin")
.last("status").as("status")
.last("createdDate").as("createdDate"));
mongoTemplate.aggregate(aggregation, "product", Product.class).getMappedResults();
It return all the documents for the given gtins (i want only the last one based on createdDate).
I tried another approach for group like this:
Aggregation.group(Fields.from(Fields.field("_id", "gtin")))
.last("status").as("status")
.last("createdDate").as("createdDate"));
But i got an exception :nested exception is java.lang.IllegalArgumentException: invalid hexadecimal representation of an ObjectId: [9788580414851]
Same if i take out "_id" from group.
Can anyone help me achieve this?
Thanks in advance.
Edit: sample documents
{
"_id": "5fc140b3f6cb564068997e7d",
"sideProductId": {
"value": "89545"
},
"createdDate": "2020-11-27T18:08:51.799Z",
"lastUpdatedDate": "2020-11-27T18:08:52.860Z",
"status": "CONCLUDED",
"direction": "SIDE1_SIDE3",
"gtin": "78902030",
"attempt": 1,
"_class": "product.Product"
}
The response from mongoaggregation after the query:
{
"_id": "78902030",
"status": "CONCLUDED",
"createdDate": "2020-11-27T18:08:50.121Z"
}
Edit 2:
Finally got it. #varman asked about the java class i was using.
Mongotemplate was mapping to the #document class, which has the _id as an ObjectId.
Had to create a new class to map it correctly with only the fields i want.
_id, status, createdDate, but _id as a String to map gtin to it.
I have a model which looks like this:
{
"projectName": "MyFirstProject",
"projectId": "1234",
"testCaseList": [
{
"testCaseName": "TestCase1",
"steps": [
{
"Action": "Click on this",
"Result": "pass"
},
{
"Action": "Click on that",
"Result": "pass"
}
]
},
{
"testCaseName": "TestCase2",
"steps": [
{
"Action": "Click on him",
"Result": "pass"
},
{
"Action": "Click on her",
"Result": "pass"
}
]
}
]
}
However, as this is a nested object, I am having difficulties updating it using the method:
default PanacheUpdate update(String update, Object... params)
I am using Repository Pattern and below is my code snippet:
List<TestCase> newTestCaseList = ...;
update("testCaseList", newTestCaseList).where("projectId=?1",projectId);
which actually throws the following error:
org.bson.json.JsonParseException: JSON reader was expecting ':' but found ','.
at org.bson.json.JsonReader.readBsonType(JsonReader.java:149)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:82)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:41)
at org.bson.codecs.BsonDocumentCodec.readValue(BsonDocumentCodec.java:101)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:84)
at org.bson.BsonDocument.parse(BsonDocument.java:63)
at io.quarkus.mongodb.panache.runtime.MongoOperations.executeUpdate(MongoOperations.java:634)
at io.quarkus.mongodb.panache.runtime.MongoOperations.update(MongoOperations.java:629)
My Current Approach
What currently works for me is to use default void update(Entity entity) instead when updating nested objects.
This however presents a few considerations:
Extra code is required to fetch the entire document, parse through, and update the required fields
Since update(Entity entity) works on a document level, it will also update unchanged parts of the document, which isn't ideal.
I guess the encountered error states nothing but a limitation of Panache for mongoDB for the moment through the standard offered PanacheQL.
The issue should be worked-around using native mongoDB Java API that can be accessed through the PanacheMongoEntityBase#mongoCollection:
mongoCollection().updateOne(
eq("projectId", projectId),
new Document("$set", new Document("testCaseList", newTestCaseList))
);
First, sorry for my poor english, but let me try to explain my problem.
I'm working in an application using elasticsearch java api for managed my documents.
Everything works fine, i'm able to search in DB and save on my index, i can count my documents aggregate by field and a lot of cool things, but i stucked on a weird problem.
When i trying to search my document by field called name, some documents doesn't return on search.
Let me give an example:
My documents is look like this(just for example):
id: 1
name: book
type: pdf
id: 2
name: Test of my search service
type: zip
When i trying to search, if i search by name, send as parameter the value "book", it works fine, but when i trying to search, send my parameter value "service", the result is empty.
Here my search code:
SearchRequestBuilder src1 = client.prepareSearch().setQuery(QueryBuilders.queryStringQuery(parameter).field("name"));
Anyone knows, why this search doesn't find my parameter value "service" on name field of document with id 2?
Thanks!
Additional information:
My general index information:
{
"template": "*",
"settings": {
"index.refresh_interval": "5s"
},
"mappings": {
"_default_": {
"_all": {
"enabled": true
},
"dynamic_templates": [
{
"string_fields": {
"match": "*",
"match_mapping_type": "string",
"mapping": {
"index": "not_analyzed",
"omit_norms": true,
"type": "string"
}
}
}
],
"properties": {
"#version": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
}
Well, after searching for hours and hours, i solved my problem.
To solve this issue, i used the wildcards query from elasticsearch java api and now i'm able to search a string parameter in my fields.
Here's the code:
SearchRequestBuilder srch1 = client.prepareSearch()
.setIndices("index_name")
.setTypes("type_name")
.setSearchType(SearchType.DFS_QUERY_AND_FETCH)
.setQuery(QueryBuilders.wildcardQuery("field_name", "*"+string_parameter+"*"));
After construction of your SearchRequestBuilder just add it into your MultipleSearchResponse or SearchResponse:
MultiSearchResponse sr = client.prepareMultiSearch()
.add(srch1)
.add(srch2)
.add(srch3)
.execute().actionGet();
In my case, i have 3 distinct queries, so i used MultipleSearchResponse.
My question is similar to this one but I am using Java Driver.
This is a document from my collection:
{
"_id": "7",
"servers": [
{
"ip_port": "127.0.0.1:8081",
"name": "server1"
},
{
"ip_port": "127.0.0.1:8082",
"name": "server2"
}
]
}
After the query I want to get a document like this:
{
"ip_port": "127.0.0.1:8081"
}
I have tried to translate the instructions of the second answer of the linked question in Java and the result was this:
MongoCursor<Document> cursor = db.getCollection("collection")
.find(and(eq("_id", "7"),
eq("servers.name", "server1")))
.projection(Projections.fields(Projections.elemMatch("servers"), Projections.excludeId()))
.iterator();
but if I execute this query and I print cursor.next().toJson() this is what I get:
{ "server" : [{ "ip_port" : "127.0.0.1:8081", "name" : "server1" }] }
So how can I get a specific embedded document inside Mongo DB with Java Driver?