Java查询Azure Cosmos DB结果超101条时触发空引用错误
问题描述
我使用Java从Azure Cosmos DB中检索数据时遇到如下报错:
com.mongodb.MongoQueryException: Query failed with error code 1 and error message '[ActivityId=92f973a7-c33f-xxxx-xxxx-xxxxxxxxxxxxx] Error=1, Details='Response status code does not indicate success: InternalServerError (500); Substatus: 0; ActivityId: 00000000-0000-0000-0000-000000000000; Reason: (Object reference not set to an instance of an object.);' on server xxxx-xxxx-westus.mongo.cosmos.azure.com:10255
用于获取数据的方法代码如下:
public List<T> getData(String orKey, String[] orValues, LinkedHashMap<String, Object> andProperties, String orderByKey, int offset, int limit) { Bson[] orFilers = new Bson[orValues.length]; int counter = 0; if (orValues.length > 0) { for (String s : orValues) { orFilers[counter++] = eq(orKey, s.trim()); } } Bson[] andFilers = new Bson[andProperties.size()]; counter = 0; if (andProperties.size() > 0) { for (Map.Entry<String, Object> entry : andProperties.entrySet()) { andFilers[counter++] = eq(entry.getKey(), entry.getValue()); } } ArrayList<T> results = new ArrayList<>(); collection.find(and(or(orFilers), and(andFilers))) .skip(offset) .limit(limit) .sort(descending(orderByKey)) .forEach((Consumer<T>) t -> { results.add(t); }); return results;
通过修改limit和offset参数调试发现,当results列表包含102条及以上记录时就会触发该错误,测试情况如下:
offset = 0 & limit = 101 => success offset = 0 & limit = 102 => error offset = 1 & limit = 102 => error offset = 1 & limit = 105 => error offset = 1 & limit = 101 => success
注:当前查询条件对应的有效记录总共有113条。
解决方案
这个报错是Azure Cosmos DB for MongoDB API的已知问题,触发原因是未索引的排序操作在结果集超过阈值时触发了服务端空指针异常,可按以下步骤修复:
- 给排序字段
orderByKey添加索引,若该查询为高频查询,建议建包含所有等值过滤字段+排序字段的复合索引,索引顺序遵循「等值过滤字段在前,排序字段在后」的规则,避免服务端做内存排序。 - 显式设置查询批次大小,调整查询代码如下:
ArrayList<T> results = new ArrayList<>(); collection.find(and(or(orFilers), and(andFilers))) .batchSize(50) // 新增此行,设置单次拉取的批次大小,避免单次拉取数据量超过服务端默认阈值 .skip(offset) .limit(limit) .sort(descending(orderByKey)) .into(results); // 可替换原forEach逻辑,代码更简洁
- 若使用的是3.2/3.6版本的Cosmos DB for MongoDB,升级到4.0及以上版本,旧版本存在多个服务端查询处理的bug,新版已完成修复。
内容的提问来源于stack exchange,提问作者Isuru Gunawardana
相关产品推荐
相关产品推荐

