我刚刚开始使用Mongo Db。以下是我的数据结构。
它有一个技能ID数组,每个数组都有一个activeCampaigns
数组,每个activeCampaign
都有一个数组callsByTimeZone
。
我在SQL术语中寻找的是:
Select activeCampaigns.callsByTimeZone.label,
activeCampaigns.callsByTimeZone.loaded
from X
where skillID=50296 and activeCampaigns.campaign_id= 11371940
and activeCampaigns.callsByTimeZone='PT'
我期待的输出是
{"label":"PT", "loaded":1 }
我使用的命令是
db.cd.find({ "skillID" : 50296 , "activeCampaigns.campaignId" : 11371940,
"activeCampaigns.callsByTimeZone.label" :"PT" },
{ "activeCampaigns.callsByTimeZone.label" : 1 ,
"activeCampaigns.callsByTimeZone.loaded" : 1 ,"_id" : 0})
我得到的结果是activeCampaigns.callsByTimeZone
下的所有内容,而我只期待PT
DataStructure:
{
"skillID":50296,
"clientID":7419,
"voiceID":1,
"otherResults":7,
"activeCampaigns":
[{
"campaignId":11371940,
"campaignFileName":"Aaron.name.121.csv",
"loaded":259,
"callsByTimeZone":
[{
"label":"CT",
"loaded":6
},
{
"label":"ET",
"loaded":241
},
{
"label":"PT",
"loaded":1
}]
}]
}
我在Java中尝试过相同的东西。
QueryBuilder query = QueryBuilder.start().and("skillID").is(50296)
.and("activeCampaigns.campaignId").is(11371940)
.and("activeCampaigns.callsByTimeZone.label").is("PT");
BasicDBObject fields = new BasicDBObject("activeCampaigns.callsByTimeZone.label",1)
.append("activeCampaigns.callsByTimeZone.loaded",1).append("_id", 0);
DBCursor cursor = coll.find(query.get(), fields);
String campaignJson = null;
while(cursor.hasNext()) {
DBObject campaignDBO = cursor.next();
campaignJson = campaignDBO.toString();
System.out.println(campaignJson);
}
获得的值是callsByTimeZone
数组下的所有内容。我目前正在解析获得的JSON并仅获取PT
个值。有没有办法只查询PT
内的activeCampaigns.callsByTimeZone
字段。
先谢谢。如果这个问题已经在论坛中提出,我已经搜索了很多,但未能找到合适的解决方案。 提前谢谢。
答案 0 :(得分:1)
有几种方法可以做到这一点,但你不应该使用字符串操作(即indexOf
),性能可能会很糟糕。
cursor
中的结果是嵌套的Maps,表示数据库中的文档 - Map是键值对的良好Java表示。因此,您可以导航到文档中所需的位置,而不必将其解析为String。我已经测试了以下内容,它可以处理您的测试数据,但如果您的数据与示例完全不同,则可能需要进行调整:
while (cursor.hasNext()) {
DBObject campaignDBO = cursor.next();
List callsByTimezone = (List) ((DBObject) ((List) campaignDBO.get("activeCampaigns")).get(0)).get("callsByTimeZone");
DBObject valuesThatIWant;
for (Object o : callsByTimezone) {
DBObject call = (DBObject) o;
if (call.get("label").equals("PT")) {
valuesThatIWant = call;
}
}
}
根据您的数据,您可能还希望针对空值添加保护。
您要查找的内容({"label":"PT", "loaded":1 }
)位于变量valueThatIWant
中。请注意,这也是一个DBObject,即Map,所以如果你想看看里面有什么,你需要使用get
:
valuesThatIWant.get("label"); // will return "PT"
valuesThatIWant.get("loaded"); // will return 1
因为DBObject实际上是一个String to Object的映射(即Map<String, Object>
),你需要转换它出来的值(因此在我的答案的第一位代码中的丑陋) - 用数字,它将取决于数据如何加载到数据库中,它可能以int或double形式出现:
String theValueOfLabel = (String) valuesThatIWant.get("label"); // will return "PT"
double theValueOfLoaded = (Double) valuesThatIWant.get("loaded"); // will return 1.0
我还想从我的回答中指出以下内容:
((List) campaignDBO.get("activeCampaigns")).get(0)
这假设“activeCampaigns”是a)一个列表,在这种情况下b)只有一个条目(我正在做get(0)
)。
您还会注意到,您设置的fields
值几乎完全被忽略,结果是大部分文档,而不仅仅是您要求的字段。我很确定你只能定义你希望查询返回的顶级字段,所以你的代码是:
BasicDBObject fields = new BasicDBObject("activeCampaigns.callsByTimeZone.label",1)
.append("activeCampaigns.callsByTimeZone.loaded",1)
.append("_id", 0);
实际上与:
完全相同BasicDBObject fields = new BasicDBObject("activeCampaigns", 1).append("_id", 0);
我认为一些有助于您使用Java和Java的要点。 MongoDB是:
DBObject
,并且这些实际上是Java中的Map<String,
Object>
- 您可以使用get
导航到正确的节点,
但是你需要将值转换成正确的形状。答案 1 :(得分:0)
使用下面的Java代码替换while循环似乎将“PT”作为输出。
`while(cursor.hasNext()) {
DBObject campaignDBO = cursor.next();
campaignJson = campaignDBO.get("activeCampaigns").toString();
int labelInt = campaignJson.indexOf("PT", -1);
String label = campaignJson.substring(labelInt, labelInt+2);
System.out.println(label);
}`