表格存储提供了GetRow接口用于读取单行数据以及BatchGetRow、GetRange等接口用于读取多行数据。

如果需要了解表格存储各场景的应用案例,请参见快速玩转Tablestore入门与实战

前提条件

  • 已初始化Client,详情请参见初始化
  • 已创建数据表并写入数据。

读取单行数据

调用GetRow接口读取一行数据。

读取的结果可能有如下两种:
  • 如果该行存在,则返回该行的各主键列以及属性列。
  • 如果该行不存在,则返回中不包含行,并且不会报错。

接口

/*
 * 根据给定的主键读取单行数据。
 */
getRow(params, callback)
                    

参数

参数 说明
tableName 数据表名称。
primaryKey 行的主键。
说明 设置的主键个数和类型必须和数据表的主键个数和类型一致。
columnsToGet 读取的列集合,列名可以是主键列或属性列。

如果不设置返回的列名,则返回整行数据。

说明
  • 查询一行数据时,默认返回此行所有列的数据。如果需要只返回特定列,可以通过设置columnsToGet参数限制。如果将col0和col1加入到columnsToGet中,则只返回col0和col1列的值。
  • 当columnsToGet和columnFilter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
maxVersions 最多读取的版本数。
说明 maxVersions与timeRange必须至少设置一个。
  • 如果仅设置maxVersions,则最多返回所有版本中从新到旧指定数量版本的数据。
  • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
  • 如果同时设置maxVersions和timeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。
timeRange 读取版本号范围或特定版本号的数据。更多信息,请参见TimeRange
说明 maxVersions与timeRange必须至少设置一个。
  • 如果仅设置maxVersions,则最多返回所有版本中从新到旧指定数量版本的数据。
  • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
  • 如果同时设置maxVersions和timeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。
  • 查询一个范围的数据,则需要设置startTime和endTime。startTime和endTime分别表示起始时间戳和结束时间戳,范围为前闭后开区间,即[startTime, endTime)
  • 如果查询特定版本号的数据,则需要设置specificTime。specificTime表示特定的时间戳。

specificTime和[startTime, endTime)中只需要设置一个。

时间戳的单位为毫秒,最小值为0,最大值为Long.MAX_VALUE。

columnFilter 使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行。更多信息,请参见过滤器
说明 当columnsToGet和columnFilter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。

示例

读取一行数据。

var TableStore = require('../index.js');
var Long = TableStore.Long;
var client = require('./client');

var params = {
  tableName: "sampleTable",
  primaryKey: [{ 'gid': Long.fromNumber(20004) }, { 'uid': Long.fromNumber(20004) }],
  maxVersions: 2 //最多可读取的版本数,设置为2即代表最多可读取2个版本。
};
var condition = new TableStore.CompositeCondition(TableStore.LogicalOperator.AND);
condition.addSubCondition(new TableStore.SingleColumnCondition('name', 'john', TableStore.ComparatorType.EQUAL));
condition.addSubCondition(new TableStore.SingleColumnCondition('addr', 'china', TableStore.ComparatorType.EQUAL));

params.columnFilter = condition;

client.getRow(params, function (err, data) {
  if (err) {
    console.log('error:', err);
    return;
  }
  console.log('success:', data);
});
                    

详细代码请参见GetRow@GitHub

批量读取数据

调用BatchGetRow接口一次请求读取多行数据,也支持一次对多张表进行读取。BatchGetRow由多个GetRow子操作组成。构造子操作的过程与使用GetRow接口时相同,也支持使用过滤器。

批量读取的所有行采用相同的参数条件,例如ColumnsToGet=[colA],则要读取的所有行都只读取colA列。

BatchGetRow的各个子操作独立执行,表格存储会分别返回各个子操作的执行结果。

注意事项

由于批量读取可能存在部分行失败的情况,失败行的错误信息在返回的BatchGetRowResponse中,但并不抛出异常。因此调用BatchGetRow接口时,需要检查返回值,判断每行的状态是否成功。

接口

/**
 * 批量读取一个或多个表中的若干行数据。
 */
batchGetRow(params, callback)                   

参数

BatchGetRow和GetRow的区别如下:
  • 增加了数据表的层级结构,可以一次读取多个数据表的数据。

    tables以数据表为单位组织,后续为各个数据表的操作,设置了需要读取的行信息。

  • primaryKey支持设置多行的主键,可以一次读取多行数据。

示例

批量一次读取多个数据表中的数据,并在出错时进行重试。

var client = require('./client');
var TableStore = require('../index.js');
var Long = TableStore.Long;

var params = {
    tables: [{
        tableName: 'sampleTable',
        primaryKey: [
            [{ 'gid': Long.fromNumber(20013) }, { 'uid': Long.fromNumber(20013) }],
            [{ 'gid': Long.fromNumber(20015) }, { 'uid': Long.fromNumber(20015) }]
        ],
        startColumn: "col2",
        endColumn: "col4"
    },
    {
        tableName: 'notExistTable',
        primaryKey: [
            [{ 'gid': Long.fromNumber(10001) }, { 'uid': Long.fromNumber(10001) }]
        ]
    }
    ],
};

var maxRetryTimes = 3;
var retryCount = 0;

function batchGetRow(params) {
    client.batchGetRow(params, function (err, data) {
        if (err) {
            console.log('error:', err);
            return;
        }

        var isAllSuccess = true;
        var retryRequest = { tables: [] };
        for (var i = 0; i < data.tables.length; i++) {
            var failedRequest = { tableName: data.tables[i][0].tableName, primaryKey: [] };

            for (var j = 0; j < data.tables[i].length; j++) {
                if (!data.tables[i][j].isOk && null != data.tables[i][j].primaryKey) {
                    isAllSuccess = false;
                    var pks = [];
                    for (var k in data.tables[i][j].primaryKey) {
                        var name = data.tables[i][j].primaryKey[k].name;
                        var value = data.tables[i][j].primaryKey[k].value;
                        var kp = {};
                        kp[name] = value;
                        pks.push(kp);
                    }
                    failedRequest.primaryKey.push(pks);

                } else {
                    // get success data
                }
            }

            if (failedRequest.primaryKey.length > 0) {
                retryRequest.tables.push(failedRequest);
            }
        }

        if (!isAllSuccess && retryCount++ < maxRetryTimes) {
            batchGetRow(retryRequest);
        }

        console.log('success:', data);
    });
}

batchGetRow(params, maxRetryTimes);                    

详细代码请参见BatchGetRow@GitHub

范围读取数据

调用GetRange接口读取一个范围内的数据。

GetRange操作支持按照确定范围进行正序读取和逆序读取,可以设置要读取的行数。如果范围较大,已扫描的行数或者数据量超过一定限制,会停止扫描,并返回已获取的行和下一个主键信息。您可以根据返回的下一个主键信息,继续发起请求,获取范围内剩余的行。

说明 表格存储表中的行都是按照主键排序的,而主键是由全部主键列按照顺序组成的,所以不能理解为表格存储会按照某列主键排序,这是常见的误区。

注意事项

GetRange操作遵循最左匹配原则,读取数据时,依次比较第一主键列到第四主键列。例如数据表的主键包括PK1、PK2、PK3三个主键列,读取数据时,优先比较PK1是否在开始主键与结束主键的范围内,如果PK1在设置的主键范围内,则不会再比较其他的主键,返回在PK1主键范围内的数据;如果PK1不在设置的主键范围内,则继续比较PK2是否在开始主键与结束主键的范围内,以此类推。关于范围查询原理的更多信息,请参见GetRange范围查询详解

GetRange操作可能在如下情况停止执行并返回数据。
  • 扫描的行数据大小之和达到4 MB。
  • 扫描的行数等于5000。
  • 返回的行数等于最大返回行数。
  • 当前剩余的预留读吞吐量已全部使用,余量不足以读取下一条数据。

接口

/**
 * 读取指定主键范围内的数据。
 */
getRange(params, callback)                   

参数

参数 说明
tableName 数据表名称。
direction 读取方向。
  • 如果值为正序(FORWARD),则起始主键必须小于结束主键,返回的行按照主键由小到大的顺序进行排列。
  • 如果值为逆序(BACKWARD),则起始主键必须大于结束主键,返回的行按照主键由大到小的顺序进行排列。

例如同一表中有两个主键A和B,A<B。如正序读取[A, B),则按从A至B的顺序返回主键大于等于A、小于B的行;逆序读取[B, A),则按从B至A的顺序返回大于A、小于等于B的数据。

inclusiveStartPrimaryKey 本次范围读的起始主键和结束主键,起始主键和结束主键需要是有效的主键或者是由INF_MIN和INF_MAX类型组成的虚拟点,虚拟点的列数必须与主键相同。

其中INF_MIN表示无限小,任何类型的值都比它大;INF_MAX表示无限大,任何类型的值都比它小。

  • inclusiveStartPrimaryKey表示起始主键,如果该行存在,则返回结果中一定会包含此行。
  • exclusiveEndPrimaryKey表示结束主键,无论该行是否存在,返回结果中都不会包含此行。

数据表中的行按主键从小到大排序,读取范围是一个左闭右开的区间,正序读取时,返回的是大于等于起始主键且小于结束主键的所有的行。

exclusiveEndPrimaryKey
limit 数据的最大返回行数,此值必须大于 0。

表格存储按照正序或者逆序返回指定的最大返回行数后即结束该操作的执行,即使该区间内仍有未返回的数据。此时可以通过返回结果中的nextStartPrimaryKey记录本次读取到的位置,用于下一次读取。

columnsToGet 读取的列集合,列名可以是主键列或属性列。

如果不设置返回的列名,则返回整行数据。

说明
  • 查询一行数据时,默认返回此行所有列的数据。如果需要只返回特定列,可以通过设置columnsToGet参数限制。如果将col0和col1加入到columnsToGet中,则只返回col0和col1列的值。
  • 如果某行数据的主键属于读取范围,但是该行数据不包含指定返回的列,那么返回结果中不包含该行数据。
  • 当columnsToGet和columnFilter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
maxVersions 最多读取的版本数。
说明 maxVersions与timeRange必须至少设置一个。
  • 如果仅设置maxVersions,则最多返回所有版本中从新到旧指定数量版本的数据。
  • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
  • 如果同时设置maxVersions和timeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。
timeRange 读取版本号范围或特定版本号的数据。更多信息,请参见TimeRange
说明 maxVersions与timeRange必须至少设置一个。
  • 如果仅设置maxVersions,则最多返回所有版本中从新到旧指定数量版本的数据。
  • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
  • 如果同时设置maxVersions和timeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。
  • 查询一个范围的数据,则需要设置startTime和endTime。startTime和endTime分别表示起始时间戳和结束时间戳,范围为前闭后开区间,即[startTime, endTime)
  • 如果查询特定版本号的数据,则需要设置specificTime。specificTime表示特定的时间戳。

specificTime和[startTime, endTime)中只需要设置一个。

时间戳的单位为毫秒,最小值为0,最大值为Long.MAX_VALUE。

columnFilter 使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行。更多信息,请参见过滤器
说明 当columnsToGet和columnFilter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
nextStartPrimaryKey 根据返回结果中的nextStartPrimaryKey判断数据是否全部读取。
  • 当返回结果中nextStartPrimaryKey不为空时,可以使用此返回值作为下一次GetRange操作的起始点继续读取数据。
  • 当返回结果中nextStartPrimaryKey为空时,表示读取范围内的数据全部返回。

示例

按照范围读取数据。

var Long = TableStore.Long;
var client = require('./client');

var params = {
  tableName: "sampleTable",
  direction: TableStore.Direction.FORWARD,
  inclusiveStartPrimaryKey: [{ "gid": TableStore.INF_MIN }, { "uid": TableStore.INF_MIN }],
  exclusiveEndPrimaryKey: [{ "gid": TableStore.INF_MAX }, { "uid": TableStore.INF_MAX }],
  limit: 50
};

client.getRange(params, function (err, data) {
  if (err) {
    console.log('error:', err);
    return;
  }

  //如果data.next_start_primary_key不为空,则继续读取。
  if (data.next_start_primary_key) {

  }

  console.log('success:', data);
});                    

详细代码请参见GetRange@GitHub