Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation on struct tags #127

Closed
ryudice opened this issue May 31, 2020 · 5 comments
Closed

Documentation on struct tags #127

ryudice opened this issue May 31, 2020 · 5 comments

Comments

@ryudice
Copy link

ryudice commented May 31, 2020

I was getting a cryptic error messages when trying to create a table, after looking at the source code I realized it was because I was missing the ID, which by the way I thought was determined by convention. The error message was index out of range [0] with length 0.

After looking at the issues I found an issue that had this struct tag dynamo:"id,hash" in the code that showed how to specify the ID. Then I looked into the documentaiton to see if this was there but couldnt find anything. Is there any place where all of the possible struct tags are doucmented? I'm still trying to specify the sort key in the code.

@guregu
Copy link
Owner

guregu commented May 31, 2020

They are sparsely documented here, at least for table creation.
https://godoc.org/github.com/guregu/dynamo#DB.CreateTable

You want to add dynamo:",range" or dynamo:"myRangeKey,range" if you want to change its name.
DynamoDB calls range keys sort keys now. Pretty confusing. You can also use the sort struct tag instead of range if you want.
Agreed that the documents and error messages need to be improved.
Also not sure what convention you thought applied here but if there's something misleading I'd like to fix it.

@chickenandpork
Copy link

chickenandpork commented Nov 14, 2020

Are these actually enums or text strings from DynamoDB ? Can you give a hint as to where we can find a list and what each does?

I'm looking at trying to make a simple datastore, but the one example seems to use the first value of a struct as automatically the Partition, the second one is the Range? Or maybe not? multiple examples, to some hints as to what the choice of markup are, or some sort of "This is how you make the 4th item the Partition Key" or "this is how you make a Range Key", or, indeed, the first element is automatically the Partition.

determined by convention

^^ positional?

We appreciate your work and that you're offering it freely, but the guesswork really increases the cost of trying things out, whereas documentation is how you help people realize the genius of your design and implementation.

What does "dynamo:ID" do?

What does "dynamo:,omitempty" do, and how does it differ from "dynamo:,omitemptyelem" ?

What does "dynamo:hash" do ? "dynamo:,hash" ? (there's a comma there)

What does "dynamo:,range" do?

What other tokens/configs/markup can we use in "dynamo:"? Is there a piece of code that lists them, that we can look at?

@guregu
Copy link
Owner

guregu commented Nov 14, 2020

@chickenandpork
Hello. Sorry about the README.md example, it was actually incorrect which could lead to quite a bit of confusion. I've removed the incorrect stuff.
The struct tags (besides hash and range etc., which are only for CreateTable, and set) have little to do with DynamoDB itself, it borrows most of its behavior from the standard library encoding/json package.
The syntax for the struct tags themselves follow the standard library's conventions, which are documented here: https://godoc.org/reflect#StructTag

I'm looking at trying to make a simple datastore, but the one example seems to use the first value of a struct as automatically the Partition, the second one is the Range? Or maybe not? multiple examples, to some hints as to what the choice of markup are, or some sort of "This is how you make the 4th item the Partition Key" or "this is how you make a Range Key", or, indeed, the first element is automatically the Partition.

You always have to specify the name of the primary keys you use for queries, it won't automatically figure them out for you. Via an overzealous PR, the example in the README incorrectly did not specify the range keys, but I have now removed those.

For example, Table.Get takes the name of the hash key as its first parameter.

You can find lots of examples here.

Note that you don't need to specify the names of the keys for Table.Put, because the underlying low-level API doesn't need them.

What does "dynamo:ID" do?

dynamo:"ID" works the same as encoding/json, it changes the fields name in the database (DynamoDB lingo: attribute name) to ID. If you don't include this, it will use the name of the struct field for the name in the database. Some people like to set their names lowercase, snake-case, etc., but if you don't care about that you don't need to set it at all.

What does "dynamo:,omitempty" do, and how does it differ from "dynamo:,omitemptyelem" ?

dynamo:",omitempty" works mostly the same as encoding/json. It omits values that are equal to their zero value. For example, an int will be omitted if it is 0. "Omitted" means that it will be treated as if it didn't exist, the data won't be written to the database at all. Unlike encoding/json, our omitempty works for structs and types with an IsZero() bool method (such as time.Time) as well.

This can be useful because DynamoDB expressions have an attribute_exists function, see here.

dynamo:",omitemptyelem" omits empty elements in slices. For example, []string{"a", ""} will be encoded as []string{"a"}. This is for feature parity with the aws-sdk-go dynamodbattribute package, you probably won't ever need it.

What does "dynamo:hash" do ? "dynamo:,hash" ? (there's a comma there)
What does "dynamo:,range" do?

dynamo:"hash" would rename the field to hash.

dynamo:",hash" would not rename the field, but mark at as the hash key so that CreateTable can generate a table definition for you (outlined here). dynamo:",range" works the same.

What other tokens/configs/markup can we use in "dynamo:"? Is there a piece of code that lists them, that we can look at?

One more important one is dynamo:",set", which tells the encoder to marshal slices and certain kinds of maps into sets instead of lists or maps.

Others that have recently been added are outlined here, however, it's likely that you won't need any of them. They exist mostly for historical reasons (DynamoDB couldn't handle empty strings until recently) or for feature parity with the official SDK. In general, it will "just work" without adding any extra tags.

The code that handles struct tags for encoding is here. The code for CreateTable starts here.

It might also be helpful to look at the item encoding tests, which cover tests for behavior of all the struct tags.

This was useful to figure out some pain points, I will use as a reference for improving the readme.

@chickenandpork
Copy link

Awesome response, @guregu :) thanks!

@guregu
Copy link
Owner

guregu commented Apr 24, 2021

finally added some documentation on struct tags in the README

@guregu guregu closed this as completed Apr 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants