简体   繁体   中英

How to access sub-document in mongoDB with condition in spring-boot program

I want to write a spring-boot program to get values of name, id, and key where abc.active is true. I have written some code

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

also, I have written class for interface.

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

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

And Abc is class.

public class Abc{

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

This is the code I am using to display output.

    @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());
        }

            }
        };
    }

Can anyone please help me with this. For any query related question do comment. Thank You in advance.

Given below is MongoDB Collection from database test. and collection name is switchrepo.

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

In response, I need output as

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

because active is true in that sub-document array.

Actual Result what I got is "abc" : [{"name" : "test","id" : "test1","key" : "secret","active" : true},{"name" : "test2","id" : "test12","key" : "secret2","active" : false}]

You cannot use property-expressions for a proprety when the the field type is an Array.

here solutions using the @Query or Aggregations

Solution 1 (Using @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).

Calling findAllWithStatus will return all SwitchRepo with at least one ABC with active is true, you need to filter (using java 8 streams filter for examples all no active Abc from array)

Solution 2 (Using Mongodb aggregation)

Create a new dto class

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;
  }
}

Create custom method Add custom method to Repository or inject MongoOperations into your service layer.

    @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;

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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