Spring Data Mongo DB Criteria查询可根据条件过滤嵌套文档

时间:2020-07-05 14:09:32

标签: mongodb spring-data-mongodb spring-mongo

我正在使用Spring Data Mongo来获取嵌套了文档的文档。 我正在尝试获取文档,如果特定条件匹配,则将嵌套文档包括在其中,或者仅给我父文档。如果任何答复,isApproved状态为true或仅获得父文档,则我需要匹配条件的父文档和嵌套文档。 以下是样本数据集,

Sample Data Set:
{
"_id" : ObjectId("5efe3d1f8a2ef008249f72d9"),
"_class" : "com.text.TestInfo",
"discussion_id" : "5efcbbdee87e6d1a706d3a4a",
"content" : "edited comment",
"title" : "Test",
"isApproved" : true,
"replies" : [
  {
  "_id" : ObjectId("59nts64j3cdcds3449f72d9"),
  "content" : "Sample text",
  "isApproved" : false
  },
  {
  "_id" : ObjectId("0j93k099vcdkfdf3vdf372d9"),
  "content" : "Sample text",
  "isApproved" : true
  }   
  ]
 },
 {
"_id" : ObjectId("5efe3d189ms908249f72d9"),
"_class" : "com.text.TestInfo",
"discussion_id" : "5efcbbdee87e6d1a706d3a4a",
"content" : "new eidted comment",
"title" : "Test",
"isApproved" : true,
"replies" : [
  {
  "_id" : ObjectId("59nts64j3cdcds3449f72d9"),
  "content" : "Sample text",
  "isApproved" : false
  }
  ]
 },
 {
"_id" : ObjectId("5efe390d9sds249f72d9"),
"_class" : "com.text.TestInfo",
"discussion_id" : "5efcbbdee87e6d1a706d3a4a",
"content" : "new eidted comment",
"title" : "Test",
"isApproved" : false,
"replies" : [
  {
  "_id" : ObjectId("59nts64j3cdcds3449f72d9"),
  "content" : "dasdsatext",
  "isApproved" : true
  }
  ]
 }

因此,以上是一个文档中的数据集,其中有两个子文档, 下一个只有一个子文档。下面是预期的输出。

Expected Output:
{
"_id" : ObjectId("5efe3d1f8a2ef008249f72d9"),
"_class" : "com.text.TestInfo",
"discussion_id" : "5efcbbdee87e6d1a706d3a4a",
"content" : "edited comment",
"title" : "Test",
"isApproved" : true,
"replies" : [
  {
  "_id" : ObjectId("0j93k099vcdkfdf3vdf372d9"),
  "content" : "Sample text",
  "isApproved" : true
  }   
  ]
},
{
"_id" : ObjectId("5efe3d189ms908249f72d9"),
"_class" : "com.text.TestInfo",
"discussion_id" : "5efcbbdee87e6d1a706d3a4a",
"content" : "new eidted comment",
"title" : "Test",
"replies" : []
}

下面是我尝试使用Spring Data MongoDB的2种方法

First Way:
Query query = new Query();
    Criteria criteria = new Criteria().andOperator(Criteria.where("discussion_id").
    is(new ObjectId("5efe3d1f8a2ef008249f72d9"))).and("replies").elemMatch(Criteria.where("isApproved").ne(true));
    query.addCriteria(criteria);
    List<TestInfo> listOfInfos = mongoOps.find(query, TestInfo.class);

结果是我收到的完全是第一份文件,这不足以满足我的要求。

Second Way:
Query query = new Query();
    Criteria criteria = new Criteria().andOperator(Criteria.where("discussion_id").
    is(new ObjectId("5efe3d1f8a2ef008249f72d9")));
    query.addCriteria(criteria);
    query.fields().elemMatch(Criteria.where("isApproved").ne(true));
    List<TestInfo> listOfInfos = mongoOps.find(query, TestInfo.class);

这里的输出仅是第一个文档中存在的答复子文档,父文档值将为空。

请告诉我我犯了什么错误

1 个答案:

答案 0 :(得分:3)

您需要使用$project。要仅返回匹配的数组元素,请使用replies.$

play

db.collection.find({
  "replies.isApproved": false
},
{
  "replies.$": 1,
  "_class": 1,
  "discussion_id": 1
})

要获取数组不匹配的其他元素:

play

db.collection.find({},
{
  "replies": {
    $elemMatch: {
      "isApproved": false
    }
  },
  "_class": 1,
  "discussion_id": 1
})

编辑:

play

db.collection.find({
  "isApproved": false
},
{
  "replies": {
    $elemMatch: {
      "isApproved": false
    }
  },
  "_class": 1,
  "discussion_id": 1
})