How can I store an array into dynamoDB table - amazon-web-services

I have the following struct:
type User struct {
ID string `json:"id"`
Name string `json:"name"`
LastName string `json:"lastName"`
User string `json:"user"`
Password string `json:"password"`
Vehicles []Vehicle `json:"vehicles"`
}
type Vehicle struct {
Plate string `json:"plate"`
}
I want to store an array of Vehicles in my DynamoDB. I did some research and I found that I should use the following code:
input := &dynamodb.PutItemInput{
TableName: aws.String(tableUsers),
Item: map[string]*dynamodb.AttributeValue{
"id": {
S: aws.String(fmt.Sprintf("%v", uuid)),
},
"name": {
S: aws.String(user.Name),
},
"lastName": {
S: aws.String(user.LastName),
},
"user": {
S: aws.String(user.User),
},
"password": {
S: aws.String(user.Password),
},
"vehicles": {
L: [{
M: {
"plate": {S: aws.String("test")},
},
}],
},
},
}
But I keep having a syntax error in:
L: [{
M: {
"plate": {S: aws.String("test")},
},
}],
What am I doing wrong?

If you look at the dynamodb's godoc: https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/#AttributeValue
You can see that the field L has the following type: []*AttributeValue
When you create a slice litteral you should specify its type.
So for you case it's:
L: []*dynamodb.AttributeValue{
{
M: map[string]*dynamodb.AttributeValue{
"plate": {S: aws.String("test")}
}
}
}
If you want to better understand struct, slices and map your can read the following articles:
https://blog.golang.org/go-slices-usage-and-internals
https://blog.golang.org/go-maps-in-action

Related

How to filter data by an object in array in DynamoDb

I want to filter data using dynamoDB QueryInput approach, the problem is in filtering data with an object in Array.
I have a data with below structure
[
{
"Pk": "mimzeslami#gmail.com",
"Sk": "social-shared-goal-2022-09-27 12:29:27",
"Gsi1Pk": "social-shared-goal",
"Gsi1Sk": "2022-09-27 12:29:27",
"Username": "test#gmail.com",
"Goals": [
{
"M": {
"Gsi2Sk": {
"S": "goal-end-2022-11-26 20:30:00"
},
"Gsi1Sk": {
"S": "goal-start-2022-09-27 12:28:47"
},
"Pk": {
"S": "mimzeslami#gmail.com"
},
"Gsi1Pk": {
"S": "mimzeslami#gmail.com"
},
"BaseCategoryId": {
"S": "85j85nachallll9idja"
},
"SubCategoryId": {
"S": "49023842874xhhiayx"
},
"Gsi2Pk": {
"S": "mimzeslami#gmail.com"
}
}
}
]
}
]
I filtered data with Username in this way:
keyCondition := map[string]*dynamodb.Condition{
Gsi1Pk: {
ComparisonOperator: aws.String(Eq),
AttributeValueList: []*dynamodb.AttributeValue{
{
S: aws.String(constants.SocialSharedGoal),
},
},
},
}
var queryFilter = map[string]*dynamodb.Condition{}
if maybeUserName != "" {
queryFilter["Username"] = &dynamodb.Condition{
ComparisonOperator: aws.String("CONTAINS"),
AttributeValueList: []*dynamodb.AttributeValue{
{
S: aws.String(maybeUserName),
},
},
}
}
params := &dynamodb.QueryInput{
KeyConditions: keyCondition,
TableName: aws.String(myTable),
IndexName: aws.String(Gsi1PkGsi1SkIndex),
Limit: &limit,
ScanIndexForward: &ascSort,
QueryFilter: queryFilter,
}
Now I want to filter data by BaseCategoryId and SubCategoryId that are in a Golas array and I don't know how to do that.
I am looking for a way like this to filter data
for example
if maybeBaseCategoryId != "" {
queryFilter[""] = &dynamodb.Condition{
ComparisonOperator: aws.String("CONTAINS"),
AttributeValueList: []*dynamodb.AttributeValue{
{S: aws.String(maybeBaseCategoryId),
},
},
}
}

DynamoDB unmarshall array of dynamodb records? (SDK v3 javascript)

I can't find a way to unmarshal an array of DynamoDB records? I'm getting multiple items back from my query in DynamoDB, and I can't use the unmarshal function that comes from #aws-sdk/util-dynamodb on an array of records. When I iterate through the array of records and unmarshal each one, that works, but this is not the best solution since I'm getting back a lot of data. How can I get DynamoDB to return multiple records without iterating through the array of records to unmarshall each one?
Code:
const client = new DynamoDBClient({ region: 'us-east-1' });
const currentDateUTC = moment().utc().format('YYYY-MM-DD');
const command = new QueryCommand({
TableName: 'Device-Data',
IndexName: 'timestamp-index',
KeyConditionExpression: '#timestamp = :timestamp',
ExpressionAttributeNames: { '#timestamp': 'timestamp' },
ExpressionAttributeValues: { ':timestamp': { S: currentDateUTC } },
});
const data = await client.send(command)
Response:
[
{
deviceId: {
S: "test1",
},
userId: {
S: "318ecd46-bead-440f-83eb-60345aaa1c40",
},
timestamp: {
S: "2022-06-12",
},
frequency: {
S: "Monthly",
},
},
{
deviceId: {
S: "test2",
},
userId: {
S: "318ecd46-bead-440f-83eb-60345aaa1c40",
},
timestamp: {
S: "2022-06-12",
},
frequency: {
S: "Monthly",
},
},
]
Desired Response:
[
{
deviceId: "test1",
userId: "318ecd46-bead-440f-83eb-60345aaa1c40",
timestamp: "2022-06-12",
frequency: "Monthly",
},
{
deviceId: "test2",
userId: "318ecd46-bead-440f-83eb-60345aaa1c40",
timestamp: "2022-06-12",
frequency: "Monthly",
},
]

Remove special characters in mongo aggregate while query run

I would like to get all the datas from mongo while i need to replace special characters, but not rewrite the data while the query run:
data in db:
[{
number: "12/34",
type: "string"
},
{
number: "56-78",
type: "string"
},
{
number: "910*2",
type: "string"
}]
the number what I would like to query is: 1234, 5678
the related output is:
[{
number: "12/34",
type: "string"
},
{
number: "56-78",
type: "string"
}]
what I try is to add field temporary without special characters, but I cannot remove all of them because addfield doesn't handle regex. i try to do this with reduce but it's not work for me.
Anybody can help me?
With MongoDB v4.2+, you can use $regexFindAll to locate all digits. Use $reduce and $concat to reconstruct a string with special characters removed/sanitized. Perform the search on the sanitized string.
db.collection.aggregate([
{
"$addFields": {
"sanitized": {
"$regexFindAll": {
"input": "$number",
"regex": "\\d"
}
}
}
},
{
"$addFields": {
"sanitized": {
"$reduce": {
"input": "$sanitized.match",
"initialValue": "",
"in": {
"$concat": [
"$$value",
"$$this"
]
}
}
}
}
},
{
"$match": {
$expr: {
"$in": [
"$sanitized",
[
"1234",
"5678"
]
]
}
}
},
{
"$project": {
sanitized: false
}
}
])
Here is the Mongo playground for your reference.

Dynamodb Query : get matched objects with filter expression

My data is stored in a table "mysettings" in DynamoDB with the following schema : "pk" as hash key and "sk" as range key
Example data item:
{
"mSettings": {
"gflag": true,
"name": "green",
"type": "B"
},
"pk": "Group1",
"sk": "A1000",
"xSettings": {
"gflag": false,
"name": "blue",
"type": "A"
},
"ySettings": {
"gflag": false,
"name": "green",
"type": "B"
},
"zSettings": {
"gflag": true,
"name": "red",
"type": "A"
}
}
Now, here I am trying to fetch(filter) only those settings where my gflag field is true.
Like for above example item, it should return only "mSettings" & "zSettings" nodes.
Below is my tried sample code:
var AWS = require('aws-sdk');
let region = "us-east-1";
AWS.config.region = region;
var docClient = new AWS.DynamoDB.DocumentClient();
let settingsItem = ["mSettings", "xSettings", "ySettings", "zSettings"];
let params = {
TableName: "mysettings",
KeyConditionExpression: "#pk = :pk AND #sk = :sk",
ExpressionAttributeNames:{
"#pk": "pk",
"#sk": "sk"
},
// FilterExpression : "ySettings.gflag = :gflag",
ExpressionAttributeValues: {
":pk": 'Group1',
":sk": 'A1000',
":gflag" : true
}
};
//for(let settings in settingsItem){
// params['FilterExpression'] = settingsItem[settings] + ".gflag = :gflag";
//}
console.log('params = ', params)
docClient.query(params, function(err, data){
if(err){
console.log(err)
}
console.log('data = ', data)
})
Kindly suggest to retrieve only those objects where flag value is true.
DynamoDB filters operate at an item level. They determine whether or not an item is returned to you. They can't be used to control which groups of attributes are returned to you. You can easily do that client-side with the query results.
Here's an example of post-processing the query results object to remove the sub-objects where gflag is not true:
const _ = require('lodash');
function gflag_true(value, key) {
return _.isObject(value) && value.gflag;
}
const item = {
"mSettings": { "gflag": true, "name": "green", "type": "B" },
"pk": "Group1",
"sk": "A1000",
"xSettings": { "gflag": false, "name": "blue", "type": "A" },
"ySettings": { "gflag": false, "name": "green", "type": "B" },
"zSettings": { "gflag": true, "name": "red", "type": "A" }
}
// transform item returned from DocumentClient query method
const rc = _.pickBy(item, gflag_true)
This results in:
{
mSettings: { gflag: true, name: 'green', type: 'B' },
zSettings: { gflag: true, name: 'red', type: 'A' }
}

Amazon DynamoDB how to read populated Database in Golang?

I have populated a local DynamoDB instance with some values from this JSON
[
{
"Id": 1,
"Type": "fruit",
"Name": "bananas",
"Price": 0.25
},
{
"Id": 2,
"Type": "fruit",
"Name": "apples",
"Price": 0.50
},
{
"Id": 3,
"Type": "fruit",
"Name": "avocados",
"Price": 1.25
},
{
"Id": 4,
"Type": "vegetable",
"Name": "carrots",
"Price": 1.00
} ]
And want to read, say all the items in this database. I believe Querying the database can do this, but in for my query input code I have
func main() {
type Product struct {
Id int `json:"Id"`
Type string `json:"Type"`
Name string `json:"Name"`
Price float64 `json:"Price"`
}
config := &aws.Config{
Region: aws.String("us-west-2"),
Endpoint: aws.String("http://localhost:8000"),
}
sess := session.Must(session.NewSession(config))
svc := dynamodb.New(sess)
input := &dynamodb.QueryInput{
TableName: aws.String("Products"),
KeyConditions: map[string]*dynamodb.Condition{
"Id": {
ComparisonOperator: aws.String("EQ"),
AttributeValueList: []*dynamodb.AttributeValue{
{
N: aws.String("1"),
},
},
},
},
}
result, err := svc.Query(input)
if err != nil {
fmt.Println(err.Error())
return
}
var products []Product
err = dynamodbattribute.UnmarshalListOfMaps(result.Items, &products)
// print the response data
for _, m := range products {
fmt.Printf("Product: '%s' (%f)\n", m.Name, m.Price)
}
}
so far and it only outputs bananas as the since the query is trying to match id = 1 (Id is my hash primary key).
I tried to modify the keycondition to something like this instead
"Id": {
ComparisonOperator: aws.String("BETWEEN"),
AttributeValueList: []*dynamodb.AttributeValue{
{
N: aws.String("0"),
},
{
N: aws.String("5"),
},
},
},
in an attempt to read every item but it says "ValidationException: Query key condition not supported". Am I doing the query statement incorrectly? Or is there some better way of listing items in dynamoDB? (Like if I wanted to list everything with "Type" == "fruit" for example, then output the first 3 items in the database.