[英]How to get just the desired field from an array of sub documents in Mongodb using Java
我刚刚开始使用Mongo Db。 下面是我的数据结构。
它具有一个SkillID数组,每个数组具有一个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
数据结构 :
{
"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
值。 有没有一种方法可以只查询activeCampaigns.callsByTimeZone
内部的PT
字段。
在此先感谢您。很抱歉,如果您已经在论坛中提出了这个问题,我已经进行了很多搜索,但未能找到合适的解决方案。 提前致谢。
有几种方法可以执行此操作,但是您不应该使用String操作(即indexOf
),否则性能可能会很糟糕。
cursor
中的结果是嵌套的Map,表示数据库中的文档-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实际上是一个字符串到对象的Map<String, 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和MongoDB的一些要点是:
DBObject
,并且它们实际上是Java中的Map<String, Object>
-您可以使用get
导航到正确的节点,但是您需要转换值变成正确的形状。 用下面的代码替换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);
}`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.