query dynamodb map field - amazon-dynamodb

I'm unable to filter dynamodb map in AWS console
Querying with mapper contains "A" works. structure of mapper is
"mapper": [
"\"A\"",
"\"B\"",
{
"bar": "foo"
}
]
How can I filter {"bar":"foo"}.
I tried
contains {"bar":"foo"}
contains '{"bar":"foo"}'
contains {bar:foo}
But none works. Please suggest.

If the mapper list is reliably ordered, the console's PartiQL editor can filter records containing {"bar": "foo"} at index 2:
select * from myTable where mapper[2].bar = 'foo'
Note: This is technically a scan operation. You can make it a query by adding WHERE conditions for your primary key.

Related

Azure Cosmos Db document partition key having duplicate, but find duplicate document with combination of other columns

I have below document JSON (pasted partial JSON, actual JSON will be complex and embedded). The JSON has Code as ParitionKey, I am trying to build No SQL database documents by migrating my sql tables, and I will have Code, Type making Unique row, as you can see below Code = 4 is duplicated with different Type and id I just generated GUID (not sure on id field so generated GUID and assigned to it).
we only have two values for Type filed, it's either RI or NRI for entire data, and Code is duplicated like below sample data Code:4, but combination of Type & Code fields make it unique.
Example JSON:
{
"id" : "88725628-2a9a-4fc7-90ed-29c5ffbd45fa"
"Code": "4",
"Type": "RI",
"Description": "MAC/CHEESE ",
},
{
"id" : "88725628-9a3b-4fc7-90ed-29c5ffbd34sk"
"Code": "8",
"Type": "RI",
"Description": "Cereals",
},
{
"id" : "88725628-6d9f-4fc7-90ed-29c4ffbd87de"
"Code": "4",
"Type": "NRI",
"Description": "Christmas Deal",
}
In NoSQL cosmos document db, I couldn't use two columns as partition key, so I have only code as Partition key, but when I am trying to insert into Cosmos Db how do I check if not exists then only insert or else I would end up creating duplicate documents:
CreateItemAsync --> I need a way to check if the document already exists if not then create
I have below code to check and if not found create Item
try
{
// Read the item to see if it exists.
ItemResponse<Item> itemResponse = await this.container.ReadItemAsync<Item>(itm.Id, new PartitionKey(itm.Code));
}
catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
// Create an item in the container representing the Andersen family. Note we provide the value of the partition key for this item, which is "Andersen"
ItemResponse<Item> itemResponse = await this.container.CreateItemAsync<Item>(itm, new PartitionKey(itm.Code));
}
But from above code in ReadItemAsync parameters, how do I know id parameter as it is a GUID randomly generated on every insert, is there a better way to utilize id property before insert into Cosmos DB, so it can be utilized while ReadItemAsync ?
second parameter is paritionKey, If I give code as partition key, it wouldn't work as expected as Code can be duplicated with different "Type" values and it's valid, but Code & Type together makes it unique and we shouldn't allow another document to be inserted if code and type are same.
How do I do it in Cosmos db insert ? I have below questions:
id field --> can I generate GUID and save document or id filed has any purpose which can be utilized during reads ?
Is it ok to pick a partition key which can potentially have duplicates like Code field.
How do I check document exists before insert with above qualifiers as Code filed can be duplicated but only With Type it makes it unique ?
Any suggestions ?
If code and type make a unique row then you should use the value of type for id as well rather than generating a GUID because in Cosmos DB the combination of your partition key and id must be unique.
Then when you do an insert, if the data is already there it will throw an exception which you can catch. For reads, if you know the value for code and type, you can use these to perform a point read to get a single row of data, rather than using a query. This is the most efficient way to fetch data in Cosmos DB.
It is fine to have duplicates for partition key values. You only need to make sure that you have less than 20GB of data for each partition key value.

make book.randomID key in amazon dynamodb table

for some reason I want to use book.randomID as key in amazon DynamoDB table using java code. when i tried id added a new field in the item named "book.randomID"
List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new KeySchemaElement().withAttributeName("conceptDetailInfo.conceptId").withKeyType(KeyType.HASH)); // Partition
and here is the json structure
{
"_id":"123",
"book":{
"chapters":{
"chapterList":[
{
"_id":"11310674",
"preferred":true,
"name":"1993"
}
],
"count":1
},
"randomID":"1234"
}
}
so is it possible to use such element as key. if yes how can we use it as key
When creating DynamoDB tables AWS limits it to the types String, Binary and Number. Your attribute book.random seems to be a String.
As long as it's not one of the other data types like List, Map or Set you should be fine.
Just going to AWS console and trying it out worked for me:

DynamoDB Descending Order fetch records

i have 100 records in collection,
collection name:'users'
{
"name":'senthilkumar',
"email":'senthily88#gmail.com', //HashKey
"age":21,
"created":1465733486137, //RangeKey-timestamp
}
i need to fetch records the following sql query wise
select * from users order by created desc limit 10
How i can get above query format records from DynamoDB
Dynamodb sorts the results by the range key attribute. You can set the ScanIndexForward boolean parameter to true for ascending or false for descending.
resource: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html
Use the KeyConditionExpression parameter to provide a specific value
for the partition key. The Query operation will return all of the
items from the table or index with that partition key value. You can
optionally narrow the scope of the Query operation by specifying a
sort key value and a comparison operator in KeyConditionExpression.
You can use the ScanIndexForward parameter to get results in forward
or reverse order, by sort key.
To Save Json Data to DynamoDB us put()
var Newparams = {
TableName: this.SuffleTableName,
Item: {
"userId": /* YOUR PRIMARY KEY */,
"addedAt": /* YOUR SORT KEY */,
"status": /* Additional Datas */,
}
}
Fetch Data From DynamoDB using Query()
QueryParam = {
TableName: 'YOUR TABLE NAME HERE',
IndexName: 'YOUR INDEX NAME HERE', //IF YOUR CREATED NEW INDEX
KeyConditionExpression: "UserId = :UserId ", //YOUR PRIMARY KEY
ExpressionAttributeValues: {
":UserId": UserId,
},
ScanIndexForward: false, //DESC ORDER, Set 'true' if u want asc order
ExclusiveStartKey: LastEvalVal, //Pagination - LastEvaluatedKeyPair
Limit: 10 //DataPerReq
}
If you want to return all rows in your table, you cannot use the query API, because that API requires you to provide a partition key value to filter your results by (i.e. assuming that your partition key is name you would only be able to use the query API to bring back the subset of results that have name = a given value, i.e. name= senthilkumar
If you want to return all rows in your table, you must use the Scan API: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SQLtoNoSQL.ReadData.Scan.html
Note that all results will be provided in ascending order by the value of the Range Key. You cannot reverse sort the contents with the Scan API. You would need to reverse your resultset in the application tier using whatever language you're writing your code in to turn the results upside down.
Scan does not scale well and it is not possible to use Scan to create a paginated, reverse sorted solution if your table contains items with unique partition keys.
If this is your situation, and if you want to return paginated + reverse sorted sets back from DynamoDB, you will need to re-consider the design of your table and which columns are the partition key/range key/index so that you can use the Query API.

DocumentDb - query on nested document and root level

Alert me | Edit | Delete | Change type
Question
You cannot vote on your own post
0
Hi!
Lets assume I have docuents in following manner:
{
id: 123,
tags: [ { name: "something" } ]
}
and I want to query all documents that contain a tag with name="searched" OR have the id=9000. I tested on playground ( https://www.documentdb.com/sql/demo )something like:
SELECT food.id, food.description, food.tags
FROM food
JOIN tag IN food.tags
WHERE food.id = "09052" or tag.name="blueberries"
but then I get a bunch of duplicate records, each document from food is times the amount of tags in that document.
How can I get distinct results when filtering on nested collection and root properties?
The ARRAY_CONTAINS built-in function might be what you need. See https://msdn.microsoft.com/library/azure/dn782250.aspx#bk_array_functions for details, i.e., something like this:
SELECT food.id, food.description, food.tags
FROM food
WHERE food.id = "09052" or ARRAY_CONTAINS(food.tags, { "name": "blueberries" })
You can test this query on the Query Playground here.
Note that the function does not use the index, so ideally you should use this when there's another filter in the query. Otherwise, the only way to do this is to use the query you had previously, then perform a "distinct" on the client side.

Updating Cassandra Map Value through querybuilder

Cassandra support updating specific value in Collection by syntax
ALTER TABLE users ADD todo map<timestamp, text>
UPDATE users SET todo['2012-10-2 12:00'] = 'throw my precious into mount doom'
WHERE user_id = 'frodo';
http://www.datastax.com/documentation/cql/3.0/cql/cql_using/use_map_t.html
Did not see any example of using QueryBuilder to update specific row in Map. How it can be done?
I think you have several options.
1/ Build your own query based on the CQL one.
Example: Consider that you have a table named Interactions and in your schema a column of type named 'attributes'.
String update ="UPDATE demo.Interactions SET attributes=attributes + {'i':'j'} where id='ff';
SimpleStatement statement = new SimpleStatement(update);
session.execute(statement);
2/ Use Java API.
Java API is not that documented indeed.
Let's take an example
a- Create an update object using queryBuilder
Update update = QueryBuilder.update(keyspace, tableName);
b- Then populate with 'put' or 'putAll' functions. put/putAll will add/update content
update.with(QueryBuilder.putAll(key, map));
To remove a key, set the content of a key to null, like:
for (Object item : map.keySet()) {
update.with(
QueryBuilder.put(columName, item, null)
);
}
Then execute the query.
Following methods are available for different types:
LIST:
QueryBuilder.appendAll(...)
QueryBuilder.discardAll(...)
SET:
QueryBuilder.addAll(...)
QueryBuilder.removeAll(...)
MAP:
QueryBuilder.putAll(...)
QueryBuilder.put(...)
The list is not exhautive.
Have a look in QueryBuilder class if you do not find what you are looking for.
Best regards and best luck with Cassandra.

Resources