Reputation: 11101
I'm learning DynamoDB and am trying to run a query using the .NET SDK for AWS. I set up a QueryRequest
with a KeyConditionExpression
defined so I can search on a partition key.
var request = new QueryRequest
{
TableName = "MyTable",
KeyConditionExpression = "ControlNumber = :cn",
ExpressionAttributeValues =
new Dictionary<string, AttributeValue> {{":cn", new AttributeValue { S = "123456789" } }}
};
var response = await client.QueryAsync(request);
I am returned the exact record I'm looking for with all the attributes. The attributes in my DynamoDB table are all defined as strings. I'm getting back data like this:
{
"scannedCount": 5,
"count": 2,
"lastEvaluatedKey": null,
"consumedCapacity": null,
"items": [
{
"Status": {
"nullvalue": null,
"ss": null,
"b": null,
"bool": null,
"ns": null,
"l": null,
"m": null,
"n": null,
"bs": null,
"s": "READY"
},
"Type": {
"nullvalue": null,
"ss": null,
"b": null,
"bool": null,
"ns": null,
"l": null,
"m": null,
"n": null,
"bs": null,
"s": "OrderStatus"
}, ......
It looks as if I get a value for every possible type of data that could be returned, in addition to my string, "s". I think these are called data type descriptors, and they are all null, except for the string data type, which contains the data I actually want to see. Why is this? And how can I get back just the data, without all those null values that I don't care about.
For example, I expect to see:
{ "Status": "Ready", "Type":"OrderStatus"....}
UPDATE: I can run a similar query or even a get-item through the AWS CLI and get back the json as I expect. So it appears the .NET SDK is adding the additional data type descriptors that I don't want to see. Also, I am using Mulesoft 4 and it does the same thing as the .NET SDK.
Upvotes: 0
Views: 1198
Reputation: 1844
This is the way it works if you are using the Document Model.
If you look at their example here you'll see that they are printing all the values by calling "PrintDocument". Looking at this code, it is looping through and printing every attribute and the value.
private static void PrintDocument(Document document)
{
// count++;
Console.WriteLine();
foreach (var attribute in document.GetAttributeNames())
{
string stringValue = null;
var value = document[attribute];
if (value is Primitive)
stringValue = value.AsPrimitive().Value.ToString();
else if (value is PrimitiveList)
stringValue = string.Join(",", (from primitive
in value.AsPrimitiveList().Entries
select primitive.Value).ToArray());
Console.WriteLine("{0} - {1}", attribute, stringValue);
}
}
If you wish to continue down this road, you'll need to build your own mapping to deal with this. So, assuming we have an InventoryItem object that consists of a status and type (as strings for simplicity) you'd end up having a mapping function like this:
private InventoryItem Map(Dictionary<string, AttributeValue> result)
{
return new InventoryItem
{
Id = Convert.ToInt32(result["Id"].N),
Status = result["Status"].S,
Type = result["Type"].S
};
}
What it sounds like you want is to use the Object Persistence Model. With this, you'll be able to create classes that map to your DynamoDB table and you can easily execute queries resulting in objects.
So, with their example you'd create a model like this:
[DynamoDBTable("Inventory")]
public class InventoryItem
{
[DynamoDBHashKey]
public int Id { get; set; }
public string Status{ get; set; }
public string Type{ get; set; }
}
And to get that item? Well, you simply have to do this:
InventoryItem inventoryItem = context.Load<InventoryItem>("123456789");
I like this method more. You can't do as many operations with it, but it is much more like Django's ORM which I am used to.
Hope this helps!
Upvotes: 1