我正在学习Accumulo,似乎无法将Range中指定的结束键包含在内。我的代码在下面。我曾尝试在Range
中将endKeyInclusive
显式设置为true
,但这没有帮助。
BatchWriter writer = conn.createBatchWriter("table", config);
List<String> deterTimes = new ArrayList<>();
String rowId = "3015551212<ll>";
String columnFamily = "deter";
for (int i = 0; i < 10; i++) {
String deterTime = "20181112:21:46:33" + i;
deterTimes.add(deterTime);
writer.addMutation(makeRecord(rowId, columnFamily, deterTime, "DETER" + i));
}
writer.flush();
writer.close();
Scanner scan = conn.createScanner("table", auths);
Key startKey = new Key(rowId.getBytes(), columnFamily.getBytes(), deterTimes.get(1).getBytes());
Key endKey = new Key(rowId.getBytes(), columnFamily.getBytes(), deterTimes.get(4).getBytes());
Range range = new Range(startKey, endKey);
if (range.isEndKeyInclusive()) System.out.println("true");
scan.setRange(range);
for (Entry<Key,Value> entry : scan) {
Text row = entry.getKey().getRow();
Text cq = entry.getKey().getColumnQualifier();
Value value = entry.getValue();
System.out.println("Fetched row " + row + " with value: " + value + ", cq=" + cq);
}
输出:
true
Fetched row 3015551212<ll> with value: DETER1, cq='20181112:21:46:331'
Fetched row 3015551212<ll> with value: DETER2, cq='20181112:21:46:332'
Fetched row 3015551212<ll> with value: DETER3, cq='20181112:21:46:333'
您正在构建将( row, column family, column qualifier )
作为字节数组的结束键,并且键( column visibility, timestamp )
的其余维度设置为默认值(具体而言,分别为空字节数组和Long.MAX_VALUE
(。
扫描仪将停止在该确切的关键点,包括在内。然而,您的实际数据输入几乎肯定不是精确的键(您没有提供makeRecord
的实现来验证(。即使您的数据实际上具有空列可见性,时间戳几乎肯定不是Long.MAX_VALUE
,而是您在makeRecord
实现中设置的,或者是基于服务器的时间或某个表逻辑计数器设置的。由于密钥的时间戳维度是按降序排列的,因此在数据到达您的条目之前,扫描仪将停止在Long.MAX_LONG
中查找数据。
这有点像在字典中搜索analogy
,但当你到达analog
时就会停止:你会错过以analog
开头的剩余单词。
当基于精确键构建范围时,这是一个常见的陷阱。通常情况下,最好基于行来构建范围(包含行将包括整行(,而不是键(有一个Range
构造函数(。或者,指定结束键,使其以独占方式工作。您可以通过在列的最后一个有意义元素的末尾附加一个空字节来实现这一点。例如,您可以执行以下操作:
Key endKey = new Key(rowId.getBytes(),
columnFamily.getBytes(),
(deterTimes.get(4) + " ").getBytes());
Range range = new Range(startKey, true, endKey, false);
您应该注意的另一个陷阱是使用String.getBytes()
获取字节数组,而不指定编码。最好使用一致的东西,比如"abc".getBytes(StandardCharsets.UTF_8)
(不过我通常会进行静态导入,所以我只能指定UTF_8
(。
Range在这里是包容性运行的,但您添加到它的值可能有问题
这将更容易用输出进行诊断,但是否有可能因为数组从零开始,所以您预期的determTime比预期的要高一个?
如果不是这样,请分享您的输出