'Error Indexes must have a projection specified' while creating a DynamoDB table with Kotlin - kotlin

While trying to create a table using the Kotlin client for DynamoDB, I'm getting this error:
Indexes must have a projection specified
aws.sdk.kotlin.services.dynamodb.model.DynamoDbException: Indexes must have a projection specified
at app//aws.sdk.kotlin.services.dynamodb.transform.CreateTableOperationDeserializerKt.throwCreateTableError(CreateTableOperationDeserializer.kt:64)
However, my table definition specifies a projection:
Projection {
projectionType = ProjectionType.All
}
This is the full table definition:
CreateTableRequest {
tableName = Config.tableName
attributeDefinitions = listOf(
AttributeDefinition { attributeName = "PK"; attributeType = ScalarAttributeType.S },
AttributeDefinition { attributeName = "SK"; attributeType = ScalarAttributeType.S },
AttributeDefinition { attributeName = "GSI1PK"; attributeType = ScalarAttributeType.S },
AttributeDefinition { attributeName = "GSI1SK"; attributeType = ScalarAttributeType.S },
)
keySchema = listOf(
KeySchemaElement { attributeName = "PK"; keyType = KeyType.Hash },
KeySchemaElement { attributeName = "SK"; keyType = KeyType.Range },
)
globalSecondaryIndexes = listOf(
GlobalSecondaryIndex {
indexName = "GSI1"
keySchema = listOf(
KeySchemaElement { attributeName = "GSI1PK"; keyType = KeyType.Hash },
KeySchemaElement { attributeName = "GSI1SK"; keyType = KeyType.Range }
)
Projection { projectionType = ProjectionType.All }
},
)
}
So, what could be missing?

Related

Adding dynamic maps in DynamoDB with Kotlin

I'm using Spring Boot, Kotlin and CrudRepository to add items to my Dynamo Table.
The map I'm trying to add is dynamic, and can change attributes every single time.
I add the date of the object (delta) and save it, but I am having several errors:
When I save:
#DynamoDBTable(tableName = "delta_computers_inventory")
class DeltaComputersInventory(
#DynamoDBHashKey
#DynamoDBAttribute(attributeName = "delta_computers_inventory_id")
var id: String = UUID.randomUUID().toString(),
#DynamoDBTyped(DynamoDBMapperFieldModel.DynamoDBAttributeType.M)
#DynamoDBAttribute(attributeName = "delta")
var delta: Map<String, Any?> = mapOf(),
) {
#DynamoDBAttribute(attributeName = "date")
var date: String = OffsetDateTime.now(ZoneOffset.UTC).format(
DateTimeFormatter.ISO_DATE_TIME
)
}
and I do:
.doOnSuccess { listOfDocuments ->
deltaComputersRepository.saveAll(
listOfDocuments.map {
DeltaComputersInventory(
delta = it,
)
}
)
}
I get:
reactor.core.Exceptions$ErrorCallbackNotImplemented: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: not supported; requires #DynamoDBTyped or #DynamoDBTypeConverted
instead, if I do it through an Item (Item.fromMap(it))
#DynamoDBTable(tableName = "delta_computers_inventory")
class DeltaComputersInventory(
#DynamoDBHashKey
#DynamoDBAttribute(attributeName = "delta_computers_inventory_id")
var id: String = UUID.randomUUID().toString(),
#DynamoDBTyped(DynamoDBMapperFieldModel.DynamoDBAttributeType.M)
#DynamoDBAttribute(attributeName = "delta")
var delta: Item = Item(),
) {
#DynamoDBAttribute(attributeName = "date")
var date: String = OffsetDateTime.now(ZoneOffset.UTC).format(
DateTimeFormatter.ISO_DATE_TIME
)
}
I get no error, but my item in my DynamoDB shows empty:
{
"delta_computers_inventory_id": {
"S": "d389d63e-8e93-4b08-b576-e37fae9a4d58"
},
"date": {
"S": "2023-01-24T12:00:33.620015Z"
},
"delta": {
"M": {}
},
}
What am I doing wrong?

Tarantool existing space migration

I need to add a parameter to existing space and keep the existing data.
space is created like this:
function create_user()
local space = box.schema.create_space('user', { engine = 'memtx' })
space:format({
{ name = 'user_id', type = 'unsigned' },
{ name = 'name', type = 'string' },
{ name = 'is_active', type = 'boolean' },
})
space:create_index('users_id', { type = 'TREE', parts = { 'user_id', 'name' } })
end
i need to add the following parameters
{ name = 'is_online', type = 'boolean' }
{ name = 'session_id', type = 'unsigned', is_nullable = true }
how to write the required migration script?
it's my solution
function migrate_users()
local counter = 0
local space = box.space.users
space:format({})
for _, tuple in space:pairs(
nil, {iterator=box.index.ALL}
) do
local user_tuple = tuple:totable()
user_tuple[4] = nil
user_tuple[5] = false
space:replace(user_tuple)
counter = counter + 1
if counter % 10000 == 0 then
fiber.sleep(0)
end
end
space:format({
{ name = 'user_id', type = 'unsigned' },
{ name = 'name', type = 'string' },
{ name = 'is_active', type = 'boolean' },
{ name = 'session_id', type = 'unsigned', is_nullable = true },
{ name = 'is_online', type = 'boolean' }
})
space:create_index('session_id', { type = 'TREE', unique = false, parts = { 'session_id' } })
end
it is better to use spacer immediately
https://github.com/igorcoding/tarantool-spacer

Importing a contact column into Podio

Which app_id should be used for importing into a contact column? Also, what should the mappings parameter look like?
podio.ImporterService.ImportAppItems(fileId, appId, new List<ImportMappingField> {
new ImportMappingField { FieldId = primaryFieldId, Unique = false, Value = new { column_id = "0" }},
new ImportMappingField { FieldId = contactfieldId, Unique = false, Value = new { column_id = "1", app_id = ???, mappings = new []{ ??? }}}
})
Edit:
I figured it out. Below is an example that works for me.
podio.ImporterService.ImportAppItems(373063497, 18803129, new List<ImportMappingField> {
new ImportMappingField {
FieldId = 148580608,
Unique = false,
Value = new { column_id = "0" }
},
new ImportMappingField {
FieldId = 148580614,
Unique = false,
Value = new {
mappings = new []{
new {
field_key = "mail",
unique = "true",
column_id = "4"
}
}
}
}
});
See the API documentation [1]
[1] https://developers.podio.com/doc/contacts

Filter dictionary array with multiple value

(
{
iReplyId = 3870;
name = rahul;
},
{
iReplyId = 3914;
name = Tom;
},
{
iReplyId = 3873;
name = Smith;
},
{
iReplyId = 3871;
name = yator;
},
{
iReplyId = 3872;
name = jack;
},
{
iReplyId = 3875;
name = smith;
},
{
iReplyId = 3876;
name = rancho;
},
{
iReplyId = 3878;
name = vid;
},
)
My requirement is to filter this array with multiple condtion like iReplyId = 3871,3870,3914 by using nspredicate. i tried so much but but i didn't get the solution with predicate, i can solve this by using for loop but that is not a good way.
Any help is highly appreciated.
[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"iReplyId IN (%#)",[idsArray componentsJoinedByString:#","]]]

How best to traverse API information with iOS

Is there any easier way of traversing array/dictionaries without creating a lot of separate NSArrays/NSDictionaries? I know you can traverse nested dictionaries with dot notation and value at keypath, but what about when arrays are involved?
For example:
At the moment if I want to get at the object at feed.entry.link[4].href in the API result below, I have to define an array at keypath "feed.entry", then assign its first entry as a dictionary, then define an array at keypath "link" and access its fourth entry as a dictionary, and then access its value at "href".
Is this normal?
received {
encoding = "UTF-8";
feed = {
entry = (
{
author = (
{
name = {
"$t" = swdestiny;
};
uri = {
"$t" = "https://gdata.youtube.com/feeds/api/users/swdestiny";
};
}
);
category = (
{
scheme = "http://schemas.google.com/g/2005#kind";
term = "http://gdata.youtube.com/schemas/2007#video";
},
{
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
term = Entertainment;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Star;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Wars;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Episode;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = 3;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Revenge;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = of;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = the;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Sith;
}
);
content = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = text;
};
"gd$comments" = {
"gd$feedLink" = {
countHint = 1567;
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/comments";
rel = "http://gdata.youtube.com/schemas/2007#comments";
};
};
"gd$rating" = {
average = "4.7729683";
max = 5;
min = 1;
numRaters = 1132;
rel = "http://schemas.google.com/g/2005#overall";
};
id = {
"$t" = "http://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
};
link = (
{
href = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata";
rel = alternate;
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/responses";
rel = "http://gdata.youtube.com/schemas/2007#video.responses";
type = "application/atom+xml";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/related";
rel = "http://gdata.youtube.com/schemas/2007#video.related";
type = "application/atom+xml";
},
{
href = "https://m.youtube.com/details?v=9kdEsZH5ohc";
rel = "http://gdata.youtube.com/schemas/2007#mobile";
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
rel = self;
type = "application/atom+xml";
}
);
"media$group" = {
"media$category" = (
{
"$t" = Entertainment;
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
}
);
"media$content" = (
{
duration = 151;
expression = full;
isDefault = true;
medium = video;
type = "application/x-shockwave-flash";
url = "https://www.youtube.com/v/9kdEsZH5ohc?version=3&f=videos&app=youtube_gdata";
"yt$format" = 5;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache4.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 1;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache5.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 6;
}
);
"media$description" = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = plain;
};
"media$keywords" = {
"$t" = "Star, Wars, Episode, 3, Revenge, of, the, Sith";
};
"media$player" = (
{
url = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata_player";
}
);
"media$thumbnail" = (
{
height = 360;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/0.jpg";
width = 480;
},
{
height = 90;
time = "00:00:37.750";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/1.jpg";
width = 120;
},
{
height = 90;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/2.jpg";
width = 120;
},
{
height = 90;
time = "00:01:53.250";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/3.jpg";
width = 120;
}
);
"media$title" = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = plain;
};
"yt$duration" = {
seconds = 151;
};
};
published = {
"$t" = "2007-05-23T03:31:54.000Z";
};
title = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = text;
};
updated = {
"$t" = "2012-02-20T17:14:37.000Z";
};
"yt$statistics" = {
favoriteCount = 763;
viewCount = 796719;
};
}
);
xmlns = "http://www.w3.org/2005/Atom";
"xmlns$gd" = "http://schemas.google.com/g/2005";
"xmlns$media" = "http://search.yahoo.com/mrss/";
"xmlns$yt" = "http://gdata.youtube.com/schemas/2007";
};
version = "1.0";
}