如何在spring-boot程序中使用条件访问mongoDB中的子文档

时间:2019-06-09 07:57:35

标签: java arrays mongodb spring-boot

我想编写一个spring-boot程序来获取name,id和key的值,其中abc.active为true。我已经写了一些代码

@Repository
public interface SwitchRepoDao extends MongoRepository< SwitchRepo, String> {
     public List<SwitchRepo> findByAbc_active(boolean active);
}

另外,我为接口编写了类。

@Document(collection="switchrepo")
public class SwitchRepo{

    @Id
    private String id;
    private String type;
    private List<Abc> abc;
    // with getters and setters also constructors.

Abc是班级。

public class Abc{

    private String name;
    private String id;
    private String key;
    private boolean active;

这是我用来显示输出的代码。

    @Bean
    CommandLineRunner runner(SwitchRepoDao switchRepoDao) {
        return new CommandLineRunner() {
            @Override
            public void run(String... args) throws Exception {          



                Iterable<SwitchRepo> personList = switchRepoDao.findAllWithStatus(true);
                System.out.println("Configuration : ");
                for (SwitchRepo config : personList)
        {
                System.out.println(config.getRegistries().toString());
        }

            }
        };
    }

有人可以帮我吗?对于任何与查询相关的问题,请做评论。预先谢谢你。

以下是数据库测试中的MongoDB集合。集合名称为switchrepo。

"_id" : "1234567890",
    "type" : "xyz",
    "abc" : [ 
        {
            "name" : "test",
            "id" : "test1",
            "key" : "secret",
            "active" : true
        }, 
        {
            "name" : "test2",
            "id" : "test12",
            "key" : "secret2",
            "active" : false
        }
    ]
}

作为回应,我需要输出为

        "id" : "test1",
        "key" : "secret",
        "active" : true

因为该子文档数组中的active为true。

实际结果是"abc" : [{"name" : "test","id" : "test1","key" : "secret","active" : true},{"name" : "test2","id" : "test12","key" : "secret2","active" : false}]

1 个答案:

答案 0 :(得分:0)

当字段类型为数组时,不能将property-expressions用于属性。

此处解决方案 using the @Query or Aggregations

解决方案1(使用@Query)

@Repository
public interface SwitchRepoDao extends MongoRepository< SwitchRepo, String> {
 //public List<SwitchRepo> findByAbc_active(boolean active);

 @Query(value = "{ 'abc.active' : ?0}", fields = "{ 'abc' : 1 }")
 List<SwitchRepo> findAllWithStatus(Boolean status);

}

{ 'abc.active' : ?0}  for filtring

{ 'abc' : 1 }         for only return that part of the document (abc).

调用findAllWithStatus会返回所有具有至少一个ABC且活动状态为true的SwitchRepo,您​​需要进行过滤(使用Java 8流过滤器,例如,数组中没有活动的Abc)

解决方案2(使用Mongodb聚合)

创建一个新的dto类

import java.util.List;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection="switchrepo")
public class SwitchRepoDto {

  @Id
  private String id;
  private String type;
  private Abc abc;
// with getters and setters also constructors.


  public SwitchRepoDto() {
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public Abc getAbc() {
    return abc;
  }

  public void setAbc(Abc abc) {
    this.abc = abc;
  }
}

创建自定义方法Add custom method to Repository或将MongoOperations注入服务层。

    @Autowired
    private MongoOperations mongoOperations;

    public List<SwitchRepoDto> findAllActive() {

        UnwindOperation unwind =  Aggregation.unwind("$abc");
        MatchOperation match = Aggregation.match(Criteria.where("abc.active").is(true));
        Aggregation aggregation = Aggregation.newAggregation(unwind,match);
        AggregationResults<SwitchRepoDto> results = mongoOperations.aggregate(aggregation, SwitchRepoDto.class, SwitchRepoDto.class);
        List<SwitchRepoDto> mappedResults = results.getMappedResults();

        return mappedResults;

}