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",
},
]
Related
EventBridge bus receives events from S3 bucket.
I need to create a rule that only handles S3 events from objects with Key prefix dir/sub-dir/ and suffix .pdf.
Tried the rule below, but it is handled as OR statement:
new events.Rule(this, 'MyRule', {
eventPattern: {
source: ['aws.s3'],
detailType: ['Object Created'],
detail: {
object: {
key: [
{ prefix: 'dir/sub-dir/' },
{
suffix: '.pdf',
},
],
},
},
},
})
Found a way to make it work, but I hope there is a better answer:
new events.Rule(this, 'MyRule', {
eventPattern: {
source: ['aws.s3'],
detailType: ['Object Created'],
detail: {
object: {
key: [
{ prefix: 'dir/sub-dir/' },
$or: [{ key: [{ suffix: '.pdf' }] }, { fieldThatDoesntExist: ['its a hack'] }],
],
},
},
},
})
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),
},
},
}
}
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
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' }
}
I don't know how to write map/reduce functions to get all film genres sorted by date of the latest film.
async function test() {
const db = new PouchDB("film")
const docs = [
{ _id: "1", title: "Rambo", year: 2008, genre: "Action" },
{ _id: "2", title: "Forrest Gump", year: 1994, genre: "Drama" },
{ _id: "3", title: "Gladiator", year: 2000, genre: "Action" },
{ _id: "4", title: "The Mask", year: 1994, genre: "Comedy" }
]
await db.bulkDocs(docs)
const fan = {
map(doc) {
emit([doc.year, doc.genre])
},
reduce(keys, values, rereduce) {
return values
}
}
const result = await db.query(fan, { group: true })
result.rows.forEach(r => console.log(r))
}
Returns:
{key: [1994, "Comedy"], value: [null]}
{key: [1994, "Drama"], value: [null]}
{key: [2000, "Action"], value: [null]}
{key: [2008, "Action"], value: [null]}
I would probably invert the order of the fields indexed.
Here's some examples:
async function test() {
const db = new PouchDB("film");
const docs = [
{ _id: "1", title: "Rambo", year: 2008, genre: "Action" },
{ _id: "2", title: "Forrest Gump", year: 1994, genre: "Drama" },
{ _id: "3", title: "Gladiator", year: 2000, genre: "Action" },
{ _id: "4", title: "The Mask", year: 1994, genre: "Comedy" }
];
await db.bulkDocs(docs);
const fan = {
map: function(doc) {
emit([doc.genre, doc.year])
},
reduce: '_count'
};
// Get the view output
const result = await db.query(fan, {
reduce: false,
include_docs: true
})
// Get a certain group
const actionFilms = await db.query(fan, {
startkey: ["Action"],
endkey: ["Action", {}],
reduce: false,
include_docs: true
});
// Get the list of groups
const genres = await db.query(fan, {
group: true,
group_level: 1
});
// Get the most recent value of a group
const lastActionFilm = await db.query(fan, {
startkey: ["Action", {}],
endkey: ["Action"],
reduce: false,
descending: true,
limit: 1,
include_docs: true
});
result.rows.forEach(r => console.log(r))
}