aws / aws-sdk-ruby-record

Official repository for the aws-record gem, an abstraction for Amazon DynamoDB.
Apache License 2.0
318 stars 41 forks source link

The table does not have the specified index: my_index #64

Closed bvirlet closed 7 years ago

bvirlet commented 7 years ago

Hello,

I'm having trouble creating a secondary index.

In my model, I define the index with:

global_secondary_index :my_index,
      hash_key: :identity_id, range_key: :range_uid, projection: { projection_type: "ALL" }

And before running my tests I have:

migration = Aws::Record::TableMigration.new(type)
migration.create!({
    provisioned_throughput: {
      read_capacity_units: 5,
      write_capacity_units: 2
    }, global_secondary_index_throughput: {
     my_index: {
       read_capacity_units: 5,
       write_capacity_units: 2,
   }
}
migration.wait_until_available

When I run my tests, I have the following error:

     Aws::DynamoDB::Errors::ValidationException:
       The table does not have the specified index: my_index

So, it seems that the migration is not actually creating the index? Do I need to do something to actually create the index?

bvirlet commented 7 years ago

Nevermind, the problem was with the index specified in the .query method which was unknown for the queried table.

awood45 commented 7 years ago

Thanks for the update. We're going to be releasing a new feature called TableConfig soon which should make migrations easier to understand and to perform, hopefully that will help somewhat.

bvirlet commented 7 years ago

Thanks @awood45 (and good to "see" you, by the way, we use to be coworkers in logistics :) !)

Also noticed that 1.0.3 has a bug where two consecutive migrations with global index creations would fail because the first would remove some parameters from an option hash from the Aws::Record (https://github.com/aws/aws-sdk-ruby-record/blob/4dded088c16bbaac8de88bf624576889b645ef88/lib/aws-record/record/secondary_indexes.rb#L95-L96), but this seems to be fixed in master. Another fix would be to clone the hash maybe?

awood45 commented 7 years ago

Hello again, I did recognize the name. :)

It does look like that was fixed with the TableConfig work, I plan on releasing that this week hopefully as 1.1.0.

awood45 commented 7 years ago

Specifically, trying to move away from TableMigration (which I could see having some edge cases) to TableConfig which uses a declarative/smart migration approach.

awood45 commented 7 years ago

Still, if you can provide the failing example, I can ensure our test suite covers the edge case in question to avoid regressions. Thanks for that extra report!

bvirlet commented 7 years ago

Here you are:

class Record
  include Aws::Record

  set_table_name 'RecordTable'

  string_attr :uid, hash_key: true

  global_secondary_index :myindex, hash_key: :uid, projection: { projection_type: "ALL" }
end

def delete_tables
  # Delete the table if already in local DynamoDB
  migration = Aws::Record::TableMigration.new(Record)
  begin
    migration.delete!
  rescue Aws::Record::Errors::TableDoesNotExist
  end
end

def migrate
  migration = Aws::Record::TableMigration.new(Record)
  migration.create!({
    provisioned_throughput: {
      read_capacity_units: 5,
      write_capacity_units: 2
    }, global_secondary_index_throughput: {
      myindex: {
        read_capacity_units: 5,
        write_capacity_units: 2,
      }
    }
  })
  migration.wait_until_available
end

delete_tables
migrate
delete_tables
migrate
Failure/Error:
  migration.create!({
    provisioned_throughput: {
      read_capacity_units: 5,
      write_capacity_units: 2
    }, global_secondary_index_throughput: {
      myindex: {
        read_capacity_units: 5,
        write_capacity_units: 2,
      }
    }

NoMethodError:
  undefined method `database_name' for nil:NilClass
awood45 commented 7 years ago

Can confirm at least that the above code works fine against the master branch.

awood45 commented 7 years ago

...and that it's broken in 1.0.3. Reopening this for the bug-report side until we push an update.

bvirlet commented 7 years ago

Yes, I confirm this works fine on master. I had to downgrade to reproduce.

ayushi-kc commented 4 years ago

I am stuck on this same issue please help me understand how does the table have the specified index? What all I have to change in order to tell table that it is the new index which I have just created in order to query that?

alextwoods commented 4 years ago

You should just need to add global_secondary_index to your model file (and depending on your use case, you'll need to run a migration first to create that index on the table).

To query using the index you can specify the index_name in the query method. Something like:

MyModel.query(
  index_name: 'my_index',
  ... #other query parameters