如何使用java对存储在游标中的mongo查询结果进行排序?
我正在使用java和MongoDB。 我在mongodb中存储了多个文档。我只想获取12个时间戳小于提供给查询的时间戳的文档 条件是查询必须选择12个时间戳更接近给定时间戳的文档 这就是我所做的如何使用java对存储在游标中的mongo查询结果进行排序?,java,mongodb,Java,Mongodb,我正在使用java和MongoDB。 我在mongodb中存储了多个文档。我只想获取12个时间戳小于提供给查询的时间戳的文档 条件是查询必须选择12个时间戳更接近给定时间戳的文档 这就是我所做的 BasicDBObject criteria = new BasicDBObject(); BasicDBObject projections = new BasicDBObject(); criteria.put("hostId",ip); criteria.put("status",0); proj
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
这给了我正确的输出,但按降序排列。
如果我按升序对文档排序,我会得到最旧的文档
我希望以升序输出,并且必须更接近给定的时间戳(时间戳小于给定时间戳的最新文档),并按升序排序
我怎样才能得到这个结果呢?让我检查一下,我是否正确理解了您的意图。您正在查找12个在给定时间之前带有时间戳的文档?例如,如果您有以下数据集(为了便于理解,我使用了非常简化的时间戳): 您搜索了时间戳10069,您希望找到该时间戳之前的12个文档,但按升序排列。你想得到文件4,5,6,7,8,9,10,11,12,13,14,15,16 您当前的代码过于复杂,这就是为什么有评论建议您检查文档的原因。但是,您实际上是部分正确的,您不能按升序排序并获得所需的值 我完全不确定你在
DBCursor cur=…
后面的代码是干什么的,把JSON和日期之类的东西弄得乱七八糟,有更简单的方法可以做到这一点,但我会让你去研究一下。然而,我已经写了一些东西,可以或多或少地满足您的查询需求,并且我已经写了一个测试来证明这是您想要的:
@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));
}
@测试
public void应使用一个用于限制标准和Sortarrayinplace(){
//给定
长时间启动点=1000;
用于(长时间戳=时间戳起始点;时间戳<1100;时间戳++){
//在数据库中插入一些具有不同时间戳的基本文档
插入(新的BasicDBObject(“timestamp”,timestamp));
}
//什么时候
long timestampToSearchFor=1050;//数据集已完成一半
//这是对早于所选时间戳的文档的查询
BasicDBObject QueryForDocumentsSolderThanTimestampToSearchFor=新BasicDBObject(“时间戳”,新BasicDBObject($lt),timestampToSearchFor));
//limit仅选择12,您必须降序排序,以使12接近所选时间戳
List foundItems=collection.find(queryForDocumentsOlderThanTimestampToSearchFor)
.限额(12)
.sort(新的BasicDBObject(“时间戳”,-1))
.toArray();
//现在,您必须按照所需的顺序对返回的数组进行排序
Collections.sort(foundItems,newcomparator(){
@凌驾
公共整数比较(最终DBObject o1,最终DBObject o2){
return(int)((Long)o1.get(“时间戳”)-(Long)o2.get(“时间戳”);
}
});
//然后
资产(foundItems.size(),为(12));
资产((Long)foundItems.get(0.get(“时间戳”)为(1038L));
资产((Long)foundItems.get(11.get)(“时间戳”)为(1049L));
}
请注意,这个解决方案在您的情况下是可以的,因为您只返回12个项目。如果结果非常大,这可能不起作用,因为整个列表都在内存中。这就是为什么通常最好在数据库中进行排序
还有另一种方法可以实现这一点,使用-可以设置一种用于限制的排序(您需要降序排序以限制到正确的12项)和第二种排序以将它们放入您想要的顺序
在我的解决方案中需要了解的关键点是:
- ,以获取早于给定值的时间戳
- 仅返回结果的子集
- 用于在Java中对数组进行排序
@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));
}