clarkie / dynogels

DynamoDB data mapper for node.js. Originally forked from https://github.com/ryanfitz/vogels

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error when accessing nested objects

pmuens opened this issue Β· comments

Hey there πŸ‘‹
Dynogels is pretty awesome! However I get the following error when trying to project fields in a deeply nested object via attributes:

ExpressionAttributeNames contains invalid key: Syntax error; key: \"#data.provider.name\"

Here's the query I'm constructing with Dynogels:

const query = this.store
  .query('some-service')
  .filter('application')
  .equals(application)
  .attributes(['name', 'data.provider.name'])
  .descending()
  .loadAll()

I think I can pin point the issue to the expressionAttributeNames creation here:

https://github.com/clarkie/dynogels/blob/v9.0.0/lib/query.js#L166-L171

Looks like the generated #data.provider.name doesn't validate since it includes dots.
Creating something like #dataProviderName when . are detected could be a potential solution here.

Just looked into this and here's the quick hack I use to solved it for now:

const { reduce, assoc, merge } = require('ramda')

function createExpressionAttributeNames (attributes, attributeNamesObject = {}) {
  return reduce(
    (accum, attribute) => {
      if (attribute.includes('.')) {
        const subAttributes = attribute.split('.')
        return merge(
          reduce(
            (accum, subAttribute) =>
              assoc(`#${subAttribute}`, subAttribute, accum),
            {},
            subAttributes
          ),
          accum
        )
      }

      return assoc(`#${attribute}`, attribute, accum)
    },
    attributeNamesObject,
    attributes
  )
}

module.exports = createExpressionAttributeNames
const { map } = require('ramda')

function createProjectionExpression (attributes) {
  return map(attribute => {
    if (attribute.includes('.')) {
      const attributeParts = attribute.split('.')
      const preparedAttributeParts = map(
        attributePart => `#${attributePart}`,
        attributeParts
      )
      return preparedAttributeParts.join('.')
    }
    return `#${attribute}`
  }, attributes).join(',')
}

module.exports = createProjectionExpression