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

Retrieve only the value of an arrays sub-document field using 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"
}]
}

如何只检索“data”字段的子字段“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);
        }

可以使用投影$project

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

工作Mongo playground

在 spring 引导中,您需要自动装配 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"));
        }

使用 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