Dynamoose - cannot query and where with 2 keys

5.6k views Asked by At

I have opened a related issue on GitHub, but maybe someone here will be able to help quicker.

Summary:

ValidationException: Query key condition not supported I need to find records in last (amount) seconds on a given location. Pretty simple, but already related to other issues: One and another one

WORKS:

Activity.query('locationId').eq(locationId).exec();

DOES NOT WORK:

Activity.query('locationId').eq(locationId).where('createdAt').ge(date).exec();

Code sample:

Schema
const Activity = (dynamoose: typeof dynamooseType) => dynamoose.model<ActivityType, {}>('Activity',
    new Schema({
      id: {
        type: String,
        default: () => {
          return uuid();
        },
        hashKey: true,
      },
      userId: {
        type: String,
      },
      locationId: {
        type: String,
        rangeKey: true,
        index: {
          global: true,
        },
      },
      createdAt: { type: Number, rangeKey: true, required: true, default: Date.now },
      action: {
        type: Number,
      },
    }, {
      expires: 60 * 60 * 24 * 30 * 3, //  activity logs to expire after 3 months
    }));
Code which executes the function

Funny part is that I found this as workaround proposed to be used until they merge PR giving ability to specify timestamps as keys, but unfortunately it does not work.

async getActivitiesInLastSeconds(locationId: string, timeoutInSeconds: number) {
    const Activity = schema.Activity(this.dynamoose);
    const date = moment().subtract(timeoutInSeconds, 'seconds').valueOf();
    return await Activity.query('locationId').eq(locationId)
      .where('createdAt').ge(date).exec();
  }
2

There are 2 answers

2
gerrytan On BEST ANSWER

I suspect createdAt is not a range key of your table / index. You need to either do .filter('createdAt').ge(date) or modify your table / index schema.

5
Charlie Fish On

I'm pretty sure the problem is that when you specifying rangeKey: true on the createdAt property you are telling that to be used on the global index (I don't think that is the correct term). That range key will be linked to the id property.

I believe the easiest solution would be to change your locationId index to be something like the following:

index: {
    global: true,
    rangeKey: 'createdAt',
},

That way you are being very explicit about which index you want to set createdAt as the rangeKey for.

After making that change please remember to sync your changes with either your local DynamoDB server or the actual DynamoDB service, so that the changes get populated both in your code and on the database system.

Hopefully this helps! If it doesn't fix your problem please feel free to comment and I'll help you further.