我正试图扫描一个DynamoDB表,获取一个位置附近的所有项目:

func getPosts(location: CLLocation, radius: Int, limit: Int){
    let rad = Double(Double(radius) * 0.01)
    let latMin = location.coordinate.latitude - rad
    let latMax = location.coordinate.latitude + rad
    let lonMin = location.coordinate.longitude - rad
    let lonMax = location.coordinate.longitude + rad

    var latMinA: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
    latMinA.N = "\(latMin)"
    var latMaxA: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
    latMaxA.N = "\(latMax)"
    var lonMinA: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
    lonMinA.N = "\(lonMin)"
    var lonMaxA: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
    lonMaxA.N = "\(lonMax)"

    var vals: [NSObject : AnyObject] = [":latMin" : latMinA, ":latMax" : latMaxA, ":lonMin" : lonMinA, ":lonMax" : lonMaxA]

    var filter = "(Latitude BETWEEN :latMin AND :latMax) and (Longitude BETWEEN :lonMin AND :lonMax)"

    self.scan("Posts", select: AWSDynamoDBSelect.AllAttributes, attributes: nil, filterAttributes: vals, startKeyName: nil, startKey: nil, limit: nil, filter: filter)
}

func scan(table: String, select: AWSDynamoDBSelect, attributes: [String]?, filterAttributes: [NSObject : AnyObject]?, startKeyName: String?, startKey: String?, limit: Int?, filter: String?){
     let dynamo: AWSDynamoDB = AWSDynamoDB.defaultDynamoDB()

     var fa: String = ""
     if(attributes != nil){
         for attribute in attributes!{
             fa+=(fa == "" ? "" : ", ")
             fa+=attribute
         }
     }

     var val: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
     val.S = startKey

     let input: AWSDynamoDBScanInput = AWSDynamoDBScanInput()
     input.tableName = table
     input.exclusiveStartKey = startKeyName != nil && startKey != nil ? [startKeyName! : val] : nil
     input.limit = limit == nil ? nil : NSNumber(unsignedInteger: limit!)
     input.filterExpression = filter
     input.expressionAttributeNames = filterAttributes
     input.select = select
     input.projectionExpression = fa == "" ? nil : fa


     dynamo.scan(input).continueWithBlock({(task: BFTask!) -> AnyObject! in
         if(task.error != nil){println("An error occurred while scanning in DynamoDB table \(table). Message: '\(task.error)'")}

         return nil
     })
 }

latMinlatMaxlonMinlonMax计算正确,所有操作正常,除非我尝试扫描表。扫描表时,我得到以下错误:
Error Domain=com.amazonaws.AWSJSONBuilderErrorDomain Code=4 "serialized object is not a valid json Object: {
  ExpressionAttributeNames =     {
    ":latMax" = "<AWSDynamoDBAttributeValue: 0x7fe1c3e6f6d0> {\n    N = \"33.820303\";\n}";
    ":latMin" = "<AWSDynamoDBAttributeValue: 0x7fe1c3ea33d0> {\n    N = \"33.740303\";\n}";
    ":lonMax" = "<AWSDynamoDBAttributeValue: 0x7fe1c3ea0cf0> {\n    N = \"-118.378292\";\n}";
    ":lonMin" = "<AWSDynamoDBAttributeValue: 0x7fe1c3e7cf90> {\n    N = \"-118.458292\";\n}";
  };
  FilterExpression = "(Latitude BETWEEN :latMin AND :latMax) and (Longitude BETWEEN :lonMin AND :lonMax)";
  Select = "ALL_ATTRIBUTES";
  TableName = Posts;
}

LatitudeLongitudeNumber数据类型,也是Local Secondary Indexes数据类型。我不解析任何JSON,都是由AWS完成的。
我试过将过滤器设置为:
var filter = "(Latitude BETWEEN \(latMin) AND \(latMax)) and (Longitude BETWEEN \(lonMin) AND \(lonMax))"

同时设置为:
var filter = "(Latitude BETWEEN 100 AND 200) and (Longitude BETWEEN 100 AND 200)"

但我还是犯了同样的错误。当我尝试将筛选器和attributeValue设置为:
var lat: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
lat.S = "Latitude"
var lon: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
lon.S = "Longitude"

var vals: [NSObject : AnyObject] = [":lat" : lat, ":lon" : lon]

var filter = "(:lat BETWEEN \(latMin) AND \(latMax)) and (:lon BETWEEN \(lonMin) AND \(lonMax))"

但我还是明白:
Error Domain=com.amazonaws.AWSJSONBuilderErrorDomain Code=4 "serialized object is not a valid json Object: {
  ExpressionAttributeNames =     {
    ":lat" = "<AWSDynamoDBAttributeValue: 0x7fd69afa77b0> {\n    S = Latitude;\n}";
    ":lon" = "<AWSDynamoDBAttributeValue: 0x7fd69afe2fc0> {\n    S = Longitude;\n}";
  };
  FilterExpression = "(:lat BETWEEN 33.740303 AND 33.820303) and (:lon BETWEEN -118.458292 AND -118.378292)";
  Select = "ALL_ATTRIBUTES";
  TableName = Posts;
}

我应该自己过滤结果,而不使用included in the AWS API的过滤器吗?

最佳答案

expressionAttributeNamesAWSDynamoDBScanInput需要是一个StringString字典。有关详细信息,请参见AWSDynamoDBScanInput Class Reference
此外,如果您使用的是框架而不是CocoaPods,请确保将dynamodb-2012-08-10.json更新到最新版本。

07-24 09:39
查看更多