使用MongoDB Java仅检索数组子文档字段的值

问题描述

我有一个数据库

{
"_id": {
    "$oid": "1"
},"lastName": {
    "lastName": "James"
},"data": [{
    "day": "20-09-2020 11:35:02","hoursWorked": "0 hours : 5 mins : 321 secs"
},{
    "day": "20-09-2020 11:35:29","hoursWorked": "0 hours : 5 mins : 321 secs"
}]
}

如何仅检索“数据”字段的子字段“ hoursWorked”的值。 因此,我只需要该字段的值或所有值,0小时:5分钟:321秒。

我使用以下内容;但是,我仍然无法检索该值。

Document document = collection
                .find(new BasicDBObject("_id",y))
                .projection(Projections.fields(Projections.include("data.hoursWorked"),excludeId())).first();
        System.out.println(document);
        }

解决方法

使用MongoDB Java驱动程序:

List<Bson> pipeline = 
    Arrays.asList(
        project(
             fields(
                 excludeId(),computed("hoursWorked",eq("$reduce",and(eq("input","$data"),eq("initialValue",Arrays.asList()),eq("in",eq("$concatArrays",Arrays.asList("$$value",Arrays.asList("$$this.hoursWorked") ) ) ) 
                          ) 
                      ) 
                  ) 
              )
          ),unwind("$hoursWorked")
    );

collection.aggregate(pipeline)
             .into(new ArrayList<Document>())
             .forEach(doc -> System.out.println(doc.get("hoursWorked")));

data数组中打印两个值:

0 hours : 5 mins : 321 secs
0 hours : 5 mins : 322 secs
,

您可以使用投影$project

db.collection.aggregate([
  {
    $project: {
      "data.hoursWorked": 1
    }
  }
])

工作Mongo playground

在春季启动中,您需要自动连接mongoTemplate

@Autowired
MongoTemplate mongoTemplate;

聚合代码

public List<Object> test(){
    Aggregation aggregation = Aggregation.newAggregation(
        a-> new Document("$project",new Document("data.hoursWorked",1)
        )

    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());

    return mongoTemplate.aggregate(aggregation,mongoTemplate.getCollectionName(YOUR_COLLECTION.class),Object.class).getMappedResults();
}

更新1

使用Bson.Doument

Document nodes = (Document) collection
                .find(new BasicDBObject("_id","1"))
                .projection(Projections.fields(Projections.include("data.hoursWorked"),Projections.excludeId()))
                .first();

        List<Document> list = (List<Document>) nodes.get("data");
        for(Document d:list){
            System.out.println(d.get("hoursWorked"));
        }