繁体   English   中英

如何使用Java从Mongodb中的子文档数组中仅获取所需字段

[英]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的一些要点是:

  • 查询数据库时,它将返回与查询匹配的内容的整个文档,即从“ skillID”开始的所有内容。 如果您想选择要返回的字段,我认为这些只会是顶级字段。 有关更多详细信息,请参见文档
  • 要导航结果,您需要知道返回了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM