Here is a question raised during our data structure design. Currently, we have a data as the following:
class {
private String id;
private Map<String, Object> map;
...
}
We will have an operation to add new entries to the map frequently. I am wondering whether the data needs to be fetched from DynamoDB first, add new entries to the map and do a DB update with the modified data or not? (That is how Mongo update works.) If not, the data structure design isn't good.
Yes, you need to fetch the data from DynamoDB first and then add a new entry to map and save the object.
If the object is of type List, then you can append values to the existing list.
List<String> nameList = new ArrayList<>();
nameList.add("1");
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", testId).withReturnValues(ReturnValue.ALL_NEW).withUpdateExpression("set #Names = list_append (#Names, :val1)").withNameMap(new NameMap().with("#Names", "Names"))
.withValueMap(new ValueMap().withList(":val1", nameList));
UpdateItemOutcome outcome = table.updateItem(updateItemSpec);
Related
I'd like to store several different object types in a single Cosmos DB container, as they are all logically grouped and make sense to read together by timestamp to avoid extra HTTP calls.
However, the Cosmos DB client API doesn't seem to provide an easy way of doing the reads with multiple types. The best solution I've found so far is to write your own CosmosSerializer and JsonConverter, but that feels clunky: https://thomaslevesque.com/2019/10/15/handling-type-hierarchies-in-cosmos-db-part-2/
Is there a more graceful way to read items of different types to a shared base class so I can cast them later, or do I have to take the hit?
Thanks!
The way I do this is to create the ItemQueryIterator and FeedResponse objects as dynamic and initially read them untyped so I can inspect a "type" property that tells me what type of object to deserialize into.
In this example I have a single container that contains both my customer data as well as all their sales orders. The code looks like this.
string sql = "SELECT * from c WHERE c.customerId = #customerId";
FeedIterator<dynamic> resultSet = container.GetItemQueryIterator<dynamic>(
new QueryDefinition(sql)
.WithParameter("#customerId", customerId),
requestOptions: new QueryRequestOptions
{
PartitionKey = new PartitionKey(customerId)
});
CustomerV4 customer = new CustomerV4();
List<SalesOrder> orders = new List<SalesOrder>();
while (resultSet.HasMoreResults)
{
//dynamic response. Deserialize into POCO's based upon "type" property
FeedResponse<dynamic> response = await resultSet.ReadNextAsync();
foreach (var item in response)
{
if (item.type == "customer")
{
customer = JsonConvert.DeserializeObject<CustomerV4>(item.ToString());
}
else if (item.type == "salesOrder")
{
orders.Add(JsonConvert.DeserializeObject<SalesOrder>(item.ToString()));
}
}
}
Update:
You do not have to use dynamic types if want to create a "base document" class and then derive from that. Deserialize into the documentBase class, then check the type property check which class to deserialize the payload into.
You can also extend this pattern when you evolve your data models over time with a docVersion property.
I need to retrieve the last row one data field. id is the primary key of my table. I'm trying to retrieve my final row data using its id
public AddExpenses[] GetFinalExpense(int numberOfExpenses)
{
return Conn.Table<AddExpenses>()
.OrderByDescending(expenses => expenses.Id)
.Take(numberOfExpenses)
.ToArray();
}
In my view model I have
var finalexpense = database.GetFinalExpense(1);
this is my code. when I tried to use this final row data to retrieve single data
ExpenseLabel = "Your expense is"+finalexpense;
in here final expense it does not show properties of the table to call. I need my finalexpense property to call it does not work
Concatenating a string with an object uses the default implementation of ToString which will yield something like AddExpenses[] for you, if finalexpense has a value !=null, since it is an array.
First of all, you'll have to get the item in the array
var finalExpenses = database.GetFinalExpense(1);
var finalExpense = finalExpenses[0];
Furthermore you'll have to make sure that your object is formatted properly. You could implement your own ToString method in AddExpenses class, but the simplest way would be to use string interpolation
var formattedExpense = $"{finalExpense.Expense} ({finalExpense.Date}, {finalExpense.Category})";
ExpenseLabel = $"Your expense is {formattedExpense}";
How you build formattedExpense is up to you, take the proposed string as a starting point and adapt it to your needs.
I have a list of class Category which contains many attributes like code, name, description, supercategory, productlist, etc. Now I want to iterate over it and retrieve each category's code and store add it in list of string. This is how I am doing it with old school way. I want to know if this can be done in better, cleaner and efficient way with Java 8 Streams.
List<Category> categories = categoryService.getCategoriesForProductCode(productCode);
List<String> categoryCodes = new ArrayList<>();
if(CollectionUtils.isNotEmpty(categories)){
for(Category cat : categories){
categoryCodes.add(cat.getCode);
}
}
You can do like this
categoryCodes = categories.stream()
.map(category->catgory.getCode()) // .map(Category::getCode)
.collect(Collectors.toList());
I have to dynamically execute queries which will come from database.The query has dynamic fields,which needs to be converted into map as key value pairs and send to view.For ex
one query may return only one fields and other may return more than two field of multiple rows.I have to write code in such way that it will work for n no.of fields and return it as map using spring jdbc.
Spring offers two ways to solve your problem.
Approach 1: use queryForList method from JdbcTemplate class. this will return List of Map populated by column names as key , and DB record as value. you have to manualy iterate over the list. each map object inside the list represents a single row in resultset.
example :
List<Map<String, Object>> result = jdbcTemplate.queryForList(query, new Object[]{123});
Iterator items = result.iterator();
while(items.hasNext()){
Map<String, Object> row = (Map<String, Object>) items.next();
System.out.println(row);
}
Approach 2 : this dosen't exactly match your requirements, but little faster than the first approach also more coding involved. you can use queryForRowSet method.
SqlRowSet rowSet = jdbcTemplate.queryForRowSet(query, new Object[]{3576});
int columnCount = rowSet.getMetaData().getColumnCount();
System.out.println(columnCount);
while(rowSet.next()){
for(int id =1 ; id <= columnCount ; id ++){
System.out.println(rowSet.getString(id)) ;
// your custom logic goes here
}
}
I'm trying to access a map column type using Astyanax.
From the examples I've taken the following. I'm looping the rows and can get the data from all the columns except the column storename which has datatype MAP. I assume I need to loop over the elements of the map to get the data into my object but I can't figure out how to do get the map data from the column.
I'm trying column.getValue and have tried getByteBuffer but can't get either to work. I can get a column object and I see there is a ColumnMap interface but I can't figure out how to get the data into an object that extends or uses it. I also see a MapSerializer interfaces but not sure how to implement that either...
List<Store> stores = new ArrayList<Store>();
for (Row<Integer, String> row : result.getResult().getRows()) {
Store store = new Store();
ColumnList<String> columns = row.getColumns();
store.setStoreID(columns.getStringValue("store_id", null));
store.setShopName(columns.getStringValue("shopname", null));
// lost trying to get the columns Map data here
// should I loop the map or pass the data straight to my store object as a map?
// How do I access the map data in this column?
for ( Map<String, String> map : columns.getValue("storename", imap, result).getResult() )
{
store.setStoreNames( "lang", "storename");
}
stores.add(store);
}
I'm a bit confused with getValue() as it takes a Serializer as it's 2nd argument and a default as it's 3rd. How do I pass the MapSerializer in as the 2nd argument or should I even be using getValue() method? Is the default a key value from the Map? If I want to return all values in the map what then? Thanks.
In the end this worked for me. And I was able to loop through the entries in the Map using the technique provided for looping maps here.
Map<String, String> map = columns.getValue("storename",
new MapSerializer<String, String>(UTF8Type.instance, UTF8Type.instance)
, new HashMap<String ,String>());