clarkie / dynogels

DynamoDB data mapper for node.js. Originally forked from https://github.com/ryanfitz/vogels
Other
490 stars 110 forks source link

Update Item #14

Closed javatask closed 7 years ago

javatask commented 8 years ago

Pls, help me with updating nested values in my complex item with this.MapModel.updateAsync(mapData). Is it possible?

{
  "map-url": "http://go.com/map",
  "access": 1,
  "price": 35.58,
  "folder": "some folder",
  "valid-from": "32/23/3222",
  "valid-until": "25/5/8545",
  "mapId": "2da491f6-65e7-478b-8231-da6baba9779c",
  "icon-url": "http://some.com/icon",
  "createdAt": "2016-07-25T15:55:20.308Z",
  "name": "test",
  "pois": [
    {
      "id": "43443",
      "phone": "+38055645",
      "category": "cat",
      "details": "long text long textlong textlong textlong textlong textlong textlong text",
      "location": {
        "long": 53.33222,
        "lat": 43.434333
      },
      "address": {
        "zip": "04050",
        "street": "pimonenko",
        "state": "jit",
        "city": "kiev"
      },
      "valid-from": "32/23/3222",
      "name": "fffdfd",
      "valid-until": "25/5/8545"
    },
    {
      "id": "43443",
      "phone": "+38055645",
      "category": "cat",
      "details": "long text long textlong textlong textlong textlong textlong textlong text",
      "location": {
        "long": 53.33222,
        "lat": 43.434333
      },
      "address": {
        "zip": "04050",
        "street": "pimonenko",
        "state": "jit",
        "city": "kiev"
      },
      "valid-from": "32/23/3222",
      "name": "fffdfd",
      "valid-until": "25/5/8545"
    }
  ],
  "area-coordinates": {
    "to": {
      "long": 53.33222,
      "lat": 43.434333
    },
    "from": {
      "long": 53.33222,
      "lat": 43.434333
    }
  }
}
clarkie commented 8 years ago

Which bit are you trying to update? What have you tried so far? What issues have you come across?

At the bottom of this section it describes updating nested data using the expressions api https://github.com/clarkie/dynogels#updating

javatask commented 8 years ago

Sorry, more detailes - all on AWS

When I'm try to update mentioned object I got an error (in the end of comment)

Model

import {
  types
} from 'dynogels';
import Joi from 'joi';

const location = {
  'lat': Joi.number(),
  'long': Joi.number()
}

const address = {
  'street': Joi.string(),
  'city': Joi.string(),
  'state': Joi.string(),
  'zip': Joi.string(),
}

const poi = {
  'id': Joi.string(),
  'name': Joi.string(),
  'location': location,
  'address': address,
  'phone': Joi.string(),
  'category': Joi.string(),
  'details': Joi.string().max(300),
  'valid-from': Joi.string(),
  'valid-until': Joi.string(),
}

export default {
  hashKey: 'mapId',

  // add the timestamp attributes (updatedAt, createdAt)
  timestamps: true,

  schema: {
    'mapId': types.uuid(),
    'name': Joi.string().required(),
    'folder': Joi.string().required(),
    'icon-url': Joi.string().uri().required(),
    'map-url': Joi.string().uri(),
    'area-coordinates': {
      'from': location,
      'to': location
    },
    'pois': Joi.array().items(poi),
    'price': Joi.number(),
    'access': Joi.any().valid([0, 1, 2, 3]).required(),
    'valid-from': Joi.string(),
    'valid-until': Joi.string()
  }
};

Service

import MapModel from './model';

class MapService {
  constructor(vogels) {
    this.MapModel = vogels.define('Maps', MapModel);
  }

  getAllMaps() {
    return new Promise((resolve, reject) => {
      this.MapModel.scan().exec((err, data) => {
        if (err) {
          reject(err);
        }
        resolve(data);
      });
    });
  }

  findMaps(title) {
    return new Promise((resolve, reject) => {
      this.MapModel.where('title').contains(title).exec((err, data) => {
        if (err) {
          reject(err);
        }

        resolve(data);
      });
    });
  }

  saveMap(mapData) {
    const map = new this.MapModel(mapData);
    return map.saveAsync();
  }

  updateMap(mapId, mapData) {
    return this.MapModel.updateAsync(mapData);
    /*return this.loadMap(mapId).then((item) => {
      console.log(item);
      return item.updateAsync(JSON.stringify(mapData));
    });*/
  }

  loadMap(mapId) {
    return this.MapModel.getAsync(mapId);
  }

  deleteMap(mapId) {
    return this.MapModel.destroyAsync(mapId);
  }
}

export default MapService;

Error

2016-07-25T16:27:16.626Z    a50b230d-5284-11e6-b6ae-07bb4db1f104    { [ValidationException: ExpressionAttributeNames contains invalid key: Syntax error; key: "#valid-until"] cause:  { [ValidationException: ExpressionAttributeNames contains invalid key: Syntax error; key: "#valid-until"] message: 'ExpressionAttributeNames contains invalid key: Syntax error; key: "#valid-until"', code: 'ValidationException', time: Mon Jul 25 2016 16:27:16 GMT+0000 (UTC), requestId: 'OMCR2DG8HLSL6N3KT37KQ4TF0RVV4KQNSO5AEMVJF66Q9ASUAAJG', statusCode: 400, retryable: false, retryDelay: 0 }, isOperational: true, code: 'ValidationException', time: Mon Jul 25 2016 16:27:16 GMT+0000 (UTC), requestId: 'OMCR2DG8HLSL6N3KT37KQ4TF0RVV4KQNSO5AEMVJF66Q9ASUAAJG', statusCode: 400, retryable: false, retryDelay: 0 }
cdhowie commented 8 years ago

According to the DynamoDB docs:

An expression attribute name must begin with a #, and be followed by one or more alphanumeric characters.

It looks like dynogels is failing to take this restriction into account when constructing the query, and since your keys contain the - character, the query fails.