Update field of a document inside an array of arrays in mongodb - java

I have a Document that has an array field called listsOfItems. Its contents are Documents and they all contain another array field called setOfItems, which is composed of Document.
So the structure is like listsOfItems(Array of Documents) > setOfItems(Array of Documents) > Items(Documents)
Each Document in listsOfItems has a listId field which is used to uniquely identify it's contents.
Each Document in setOfItems has a itemId field which is used to uniquely identify it's contents.
I want to change the value of a field inside a Document of setOfItems given the listId and itemId.
Currently, I'm trying to do it like this:
final var filter = Filters.and(Filters.eq("accessDetail.email", email),
Filters.eq("listsOfItems.listId", listId),
Filters.eq("listsOfItems.$.setOfItems.itemId", itemId));
final var updateQuery = Updates.set("listsOfItems.$.setOfItems.obtained", BsonBoolean.TRUE);
usersCollection.findOneAndUpdate(filter, updateQuery)
The query doesn't match any Document
I cannot access the elements in the setOfItems by directly accessing them by index because they are ordered by other indexes and not according to their itemId field.
What is the right query for performing the update given the condition?
EDIT1
I have replaced my filter to:
final var filter = Filters.and(Filters.eq("accessDetail.email", email),
Filters.elemMatch("listsOfItems",
Filters.eq("listId", listId)),
Filters.elemMatch("listsOfItems.setOfItems",
Filters.eq("itemId", itemId)));
Now I get the error message: 'Cannot create field 'obtained' with the correct sub-document that it should make changes in.
The issue boils down to the updateQuery.

To do this, you need to make use of arrayFilters.
Document filter = new Document("base-doc-field","<value>");//query for base doc
//fields if any
Document updateDoc = new Document("$inc",
new Document("listOfItems.$[elem].setOfItems.$[elem1].fieldName","value to
update"));
//prepare array filters.
List<Bson> arrayFilters = new ArrayList<>();
arrayFilters.add(new Document("elem.listId","<list_id>"));
arrayFilters.add(new Document("elem1.itemId","<item_id>"));
//prepare update options, and set these array filters to update options.
UpdateOptions options = new UpdateOptions().
arrayFilters(filterArr).bypassDocumentValidation(true);
//execute update method.
collection.updateOne(filter,updateDoc,options);
Visit https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#update-nested-arrays-in-conjunction-with

Related

How to do pagination with DynamoDBMapper?

I'm developing an application in Quarkus that integrates with the DynamoDB database. I have a query method that returns a list and I'd like this list to be paginated, but it would have to be done manually by passing the parameters.
I chose to use DynamoDBMapper because it gives more possibilities to work with lists of objects and the level of complexity is lower.
Does anyone have any idea how to do this pagination manually in the function?
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
.withLimit(pageSize)
.withExclusiveStartKey(paginationToken);
PaginatedScanList<YourModel> result = mapper.scan(YourModel.class, scanExpression);
String nextPaginationToken = result.getLastEvaluatedKey();
You can pass the pageSize and paginationToken as parameters to your query method. The nextPaginationToken can be returned along with the results, to be used for the next page.
DynamoDB Mapper paginates by iterating over the results, by lazily loading the dataset:
By default, the scan method returns a "lazy-loaded" collection. It initially returns only one page of results, and then makes a service call for the next page if needed. To obtain all the matching items, iterate over the result collection.
Ref
For example:
List<Customer> result = mapper.scan(Customer.class, scanExpression);
for ( Customer cust : result ) {
System.out.println(cust.getId());
}
To Scan manually page by page you can use ScanPage
final DynamoDBScanExpression scanPageExpression = new DynamoDBScanExpression()
.withLimit(limit);
do {
ScanResultPage<MyClass> scanPage = mapper.scanPage(MyClass.class, scanPageExpression);
scanPage.getResults().forEach(System.out::println);
System.out.println("LastEvaluatedKey=" + scanPage.getLastEvaluatedKey());
scanPageExpression.setExclusiveStartKey(scanPage.getLastEvaluatedKey());
} while (scanPageExpression.getExclusiveStartKey() != null);
Ref
Ref

API xml response looping and extract all the element values - Groovy

Below is the snapshot of my API XML response
<Plaintiff>
<PlaintiffName>SEB B.A.
</PlaintiffName>
<PlaintiffName>SEB??
</PlaintiffName>
</Plaintiff>
I want to extract all the PlaintiffName under the Plaintiff node.
Code:
String caseResponseText = response.getResponseText()
def xmlResult = new XmlSlurper().parseText(caseResponseText)
def plaintiff = xmlResult.Case.Plaintiff.PlaintiffName[0].text()
The above one i got the result of first plaintiff name / second plaintiff name. But how should i looping thru this node and get all the palintiff value dynamically?
Because response may have only one plaintiff or more than one, so I need to parse dynamically and get all the values thru looping
Simply loop over the nodes:
def plaintiffs = xmlResult.Case.Plaintiff.PlaintiffName
for (plaintiff in plaintiffs) {
// do something with plaintiff
}

How to access a variable from java objects in a java collection?

I am using Mongo Java Driver, and I am trying to use filters on the collection.find() function. For example, when I have a key which is a java object, the class of which contains certain fields:
Document document = (Document) collection.find(and(
eq("m_seniority", key.getM_seniority()),
eq("m_currency",key.getM_currency()),
eq("m_redCode",key.getM_redCode()),
eq("m_companyId",key.getM_companyId())
)).first();
I use the above command. But when I want to do that in bulk, I am being passed a collection of keys, ( Collection keys ), I can't access particular variables of the java objects inside as below:
List<Document> docs = (List<Document>) collection.find(and(
eq("m_seniority", keys.getM_seniority()),
eq("m_currency",keys.getM_currency()),
eq("m_redCode",keys.getM_redCode()),
eq("m_companyId",keys.getM_companyId())
)).into(new ArrayList<Document>());
Because getters are not of the collection, but just the objects, i can't use getters on the collection. How do I do this?
To create an or query on all of the Collection keys:
List<Bson> keyFilters = new ArrayList<>();
// for each key create an 'and' filter on seniority, currency, redcode and companyid
for (Key key : keys) {
keyFilters.add(
Filters.and(eq("m_seniority", key.getM_seniority()),
Filters.eq("m_currency",key.getM_currency()),
Filters.eq("m_redCode",key.getM_redCode()),
Filters.eq("m_companyId",key.getM_companyId())
)
);
}
List<Document> docs = (List<Document>) collection.find(
// 'or' all of the individual key filters
Filters.or(keyFilters)
).into(new ArrayList<Document>());

Get the single value from mongodb Collection using java code

I want to get only the single value from Mongodb Collection.
Currently i am getting the Document which is FindIterable.
CustomObject obj = db
.getCollection("Collection",CustomObject.class)
.find(and(eq("field1", new BigDecimal(10409)),eq("field2", new BigDecimal(1))));
But , i dont want any result in to the Object or List.like in Oracle we use Query to get single Object :
SELECT NAME FROM EMPLOYEE_TABLE WHERE ID=10 AND DEPT_ID=23;
This query gives us the Single name of the employee on the basis of filter conditions, and we get the output in String type Object.
Same i want to get from the mongodb , i don't want to use any bean to populate the data. i want only single String object as result.
You may use the find method on Collection, passing a query and fields to retrieve:
BasicDBObject fields = new BasicDBObject();
fields.put("name", true);
BasicDBObject query = new BasicDBObject();
query.put("id", 13);
query.put("dept_id", 23);
DBCursor find = mongoTemplate.getCollection("example").find(query, select);
List<DBObject> list = find.toArray();
List<String> names = list.stream().map(o -> String.valueOf(o.get("name"))).collect(Collectors.toList());
If you are seeking for a function that returns just one document, then you can use findOne.

How to add all row elements in database to JSON object

I'm trying to retrieve all elements in database and display in webpage.But with my code it able to retrieve only one row element. Problem is, it retrieves all element but it adds the last row element to the object. I think all elements retrieved first are overwritten Because of that it displays last row element. Can anyone tell me how add all row elements to the JSON object. Please help me.
code :
while(rs.next()){
ImageFile.setName(rs.getString("imagename").trim());
ImageFile.setDisc(rs.getString("imagedisc").trim());
ImageFile.setImageid(rs.getInt("imageid"));
ImageFile.setalbumid(rs.getInt("albumid"));
byte imageData[] = rs.getBytes("imagethumb");
String encoded = DatatypeConverter.printBase64Binary(imageData);
ImageFile.setThumb(encoded);
byte image1Data[] = rs.getBytes("imagethumb");
String encoded1 = DatatypeConverter.printBase64Binary(image1Data);
ImageFile.setFull(encoded1);
}
The complete source code is in this question
Please help me........Thanks....
Use a list Collection to keep all the row-values of db, like - List<ImageFileInfo> which denotes List containing of ImageFileInfo Objects . And then serialize the list to json String.
List<ImageFileInfo> imageFileList = new ArrayList<ImageFileInfo>();
while(rs.next()){
ImageFileInfo info = new ImageFileInfo();
info..setName(rs.getString("imagename").trim());
...
imageFileList.add(info);
}
Json serialization -
Type typeOfList= new TypeToken<List<ImageFileInfo>>(){}.getType();
String s = gson.toJson(imageFileList , typeOfList);

Categories

Resources