我正在使用java和mongo db。 我在mongodb中存储了多个文档。我想只获取12个文档,这些文档的时间戳小于为查询提供的时间戳。
条件是查询必须选择12个文档,其时间戳更接近给定的时间戳。
这是我做的事情?
BasicDBObject criteria = new BasicDBObject();
BasicDBObject projections = new BasicDBObject();
criteria.put("hostId",ip);
criteria.put("status",0);
projections.put("runtimeMillis",1);
projections.put("cpuUtilization",1);
String json_string="";
DBCursor cur = coll.find(criteria,projections).sort(new BasicDBObject("runtimeMillis",-1)).limit(12);
Object[] row = createOutputRow(new Object[0], outputRowSize);
int index = 0;
String mystring = null;
List list = new ArrayList();
JSONObject result = new JSONObject();
json_string = "[";
while(cur.hasNext() && !isStopped()) {
String json = cur.next().toString();
JSONObject responseObject = new JSONObject(json);
long convert = Long.parseLong(responseObject.getString("runtimeMillis"));
long set_date = convert;
Date dateObj = new Date(set_date);
String date_text = ft.format(dateObj);
int month = 0;
month = Integer.parseInt(new java.text.SimpleDateFormat("MM").format(dateObj));
/json_string +="{x: ("+convert+"),y: "+responseObject.getString("cpuUtilization")+", color: \"red\"},";
}//end of while
这给了我正确的输出但是按降序排列。 如果我按升序对文档进行排序,我会得到最旧的文档。
我希望按升序输出,并且必须更接近给定的时间戳(时间戳小于给定时间戳的最新文档)并按升序排序。
我如何得到这个结果?
答案 0 :(得分:0)
让我检查一下我是否理解你正在尝试做什么。您是否在给定时间之前查找带有时间戳的12个文档?因此,例如,如果您有以下数据集(我使用非常简化的时间戳以便于理解):
{ documentNumber: 1, timestamp: 1002 },
{ documentNumber: 2, timestamp: 1003 },
{ documentNumber: 3, timestamp: 1005 },
{ documentNumber: 4, timestamp: 1007 },
{ documentNumber: 5, timestamp: 10011 },
{ documentNumber: 6, timestamp: 10013 },
{ documentNumber: 7, timestamp: 10017 },
{ documentNumber: 8, timestamp: 10019 },
{ documentNumber: 9, timestamp: 10023 },
{ documentNumber: 10,timestamp: 10031 },
{ documentNumber: 11,timestamp: 10037 },
{ documentNumber: 12,timestamp: 10041 },
{ documentNumber: 13,timestamp: 10053 },
{ documentNumber: 14,timestamp: 10057 },
{ documentNumber: 15,timestamp: 10063 },
{ documentNumber: 16,timestamp: 10065 },
{ documentNumber: 17,timestamp: 10069 },
{ documentNumber: 18,timestamp: 10074 },
{ documentNumber: 19,timestamp: 10079 }
并且您搜索了时间戳10069,您希望在该时间戳之前找到12个文档,但是按升序排列。所以你想获得文件4,5,6,7,8,9,10,11,12,13,14,15,16?
您当前的代码非常复杂,这就是建议您查看文档的评论。但是,您实际上是部分正确的,您无法按升序排序和获取所需的值。
我完全不确定DBCursor cur = ...
之后你的代码是什么,用JSON和Dates弄乱,东西看起来很毛茸茸,而且有更简单的方法可以做到这一点,但是我会让你研究那个。但是,就查询而言,我已经写了一些应该给你或多或少的东西的东西,并且我已经写了一个测试来证明这符合你的要求:
@Test
public void shouldUseASortForLimitCriteriaAndSortArrayInPlace() {
// given
long timestampStartingPoint = 1000;
for (long timestamp = timestampStartingPoint; timestamp < 1100; timestamp++) {
//insert some basic documents into the database with different timestamps
collection.insert(new BasicDBObject("timestamp", timestamp));
}
// when
long timestampToSearchFor = 1050; // halfway through the data set
// this is the query for documents older than a chosen timestamp
BasicDBObject queryForDocumentsOlderThanTimestampToSearchFor = new BasicDBObject("timestamp", new BasicDBObject("$lt", timestampToSearchFor));
// limit selects only 12, you have to sort descending to get the 12 closes to the selected timestamp
List<DBObject> foundItems = collection.find(queryForDocumentsOlderThanTimestampToSearchFor)
.limit(12)
.sort(new BasicDBObject("timestamp", -1))
.toArray();
// now you have to sort the returned array into the order you want
Collections.sort(foundItems, new Comparator<DBObject>() {
@Override
public int compare(final DBObject o1, final DBObject o2) {
return (int) ((Long) o1.get("timestamp") - (Long) o2.get("timestamp"));
}
});
// then
assertThat(foundItems.size(), is(12));
assertThat((Long) foundItems.get(0).get("timestamp"), is(1038L));
assertThat((Long) foundItems.get(11).get("timestamp"), is(1049L));
}
请注意,此解决方案适用于您的情况,因为您仅 返回12个项目。如果结果非常大,这可能不工作,因为整个列表将在内存中。这就是为什么在数据库中进行排序通常会更好。
还有另一种方法可以实现这一点,使用aggregation framework - 这将允许您设置一种用于限制的排序(您需要按降序排序以限制为正确的12项)和第二种排序将它们按照你想要的顺序排列。
我的解决方案中要理解的关键点是:
我还建议您查看Aggregation的文档。