我创建了一个包含以下内容的表格:
[{
device_id: '2',
timestamp: 1498331237262
gateway: 'gateway1',
temperature: 20,
humidity: 30,
pressure: 101049,
lat: 2,
long: 1
},
{
device_id: '2',
timestamp: 1498331237261,
gateway: 'gateway1',
temperature: 20,
humidity: 30,
pressure: 101049
}]
主分区键:device_id
(字符串)
主要排序键:timestamp
(数字)
我正在尝试获取具有timestamp
和lat
属性的最新(long
}项。
我目前的破坏尝试如下:
const params = {
TableName: 'device_telemetry',
KeyConditionExpression: 'device_id = :id AND ',
ProjectionExpression: '#lat, #lng, #ts',
FilterExpression: 'attribute_exists(#lat) AND attribute_exists(#lng)',
ExpressionAttributeNames: {
'#lat': 'lat',
'#lng': 'long',
'#ts': 'timestamp'
},
ExpressionAttributeValues: {
':id': row['device_id'].toString(),
':startDate': row['departure_date'].getTime()
},
ScanIndexForward: false,
Limit: 1
};
if (row['eta'] === null) {
params.KeyConditionExpression += '#ts >= :startDate';
} else {
params.KeyConditionExpression += '#ts BETWEEN :startDate AND :endDate';
params.ExpressionAttributeValues[':endDate'] = row['eta'].getTime();
}
const onResult = (res) => {
console.info('devices res for: ', row['device_id'], res);
if (res.Items.length > 1) {
console.info(res.Items);
throw new Error('Query returned more than 1 item: ' + params);
}
return res.Items[0];
};
console.info('query: ', params);
docClient.query(params).promise().then(onResult);
据我所知,ScanIndexForward: false, Limit: 1
对KeyConditionExpression
执行后获得的结果进行操作,然后运行FilterExpression
,这意味着在第一步中我会对此进行操作可能得到一个没有必要属性的项目然后被过滤掉。
最好的方法是什么?我是NoSQL概念的初学者,我知道除了得到正确的结果外,我还必须考虑数据的桶分配。
提前谢谢。
答案 0 :(得分:0)
这是一个有点hacky解决方案,但我想不出任何其他方式,你可以避免超过1个查询满足您的需求:
您可以通过添加前缀将lat + long的存在或不存在编码到时间戳中。示例:“withCoord_timestamp”。这将允许您修改范围键查询,以便不再需要过滤表达式,因此您将始终获得1个结果。