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.
Related
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:"
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))
);
I have a collection for status update of an order service. Each document in this collection is a new update for this Order.
The Document is like this:
{
"_id": "xxx",
"orderNumber": 1,
"notificationDate": ISODate("2019-06-01T20:25:43.280Z"),
"description": "Something"
}
I must found every order with no update in this month, so I made this query:
db.notificationData.find({"$and": [
{"orderNumber": {"$nin" :
db.notificationData.find({notificationDate: {"$gt": ISODate("2019-06-01") }})
.map(function(data) { return data.orderNumber})
}},
{notificationDate: {"$lt": ISODate("2019-06-01") }}
]});
There is a way to get the same result using Spring Data MongoDB??
I am having a problem while querying elastic search. The below is my query
GET _search {
"query": {
"bool": {
"must": [{
"match": {
"name": "SomeName"
}
},
{
"match": {
"type": "SomeType"
}
},
{
"match": {
"productId": "ff134be8-10fc-4461-b620-79s51199c7qb"
}
},
{
"range": {
"request_date": {
"from": "2018-08-22T12:16:37,392",
"to": "2018-08-28T12:17:41,137",
"format": "YYYY-MM-dd'T'HH:mm:ss,SSS"
}
}
}
]
}
}
}
I am using three match queries and a range query in the bool query. My intention is getting docs with these exact matches and with in this date range. Here , if i change name and type value, i wont get the results. But for productId , if i put just ff134be8, i would get results. Anyone knows why is that ? . The exact match works on name and type but not for productId
You need to set the mapping of your productId to keyword to avoid the tokenization. With the standard tokenizer "ff134be8-10fc-4461-b620-79s51199c7qb" will create ["ff134be8", "10fc", "4461", "b620", "79s51199c7qb"] as tokens.
You have different options :
1/ use a term query to check without analyzing the content of the field
...
{
"term": {
"productId": "ff134be8-10fc-4461-b620-79s51199c7qb"
}
},
...
2/ if you are in Elasticsearch 6.X you could change your request to
...
{
"match": {
"productId.keyword": "ff134be8-10fc-4461-b620-79s51199c7qb"
}
},
...
As elasticsearch will create a subfield keyword with the type keyword for all string field
The best option is, of course, the first one. Always use term query if you are trying to match the exact content.
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.