복붙노트

[MONGODB] 봄의 데이터 - MongoDB를 - 중첩 된 객체에 대한 findBy 방법

MONGODB

봄의 데이터 - MongoDB를 - 중첩 된 객체에 대한 findBy 방법

나는 두 개의 도메인 개체가

@Document
public class PracticeQuestion {

     private int userId;
     private List<Question> questions;

// Getters and setters
}

@Document
public class Question {

     private int questionID;
     private String type;

// Getters and setters
}

내 JSON의 문서는 다음과 같이이다

{
    "_id" : ObjectId("506d9c0ce4b005cb478c2e97"),
    "userId" : 1,
    "questions" : [
        {
            "questionID" : 1,
            "type" : "optional"

         },
        {
             "questionID" : 3,
             "type" : "mandatory"
        }
    ]
}

나는 사용자 정의 저장소 인터페이스 내부에 findBy 쿼리 방법을 쓴, 그래서 나는, ID 및 questionId에 따라 "유형"을 업데이트해야

public interface CustomRepository extends MongoRepository<PracticeQuestion, String> {

    List<PracticeQuestion> findByUserIdAndQuestionsQuestionID(int userId,int questionID);       
}

내가 3과 같이 1과 ID 및 questionID이 방법을 실행하면 내 문제는 전체 질문에 관계없이 questionID의 목록을 반환합니다. query 메소드 이름이 잘못인가, 아니면 내가 어떻게 중첩 된 개체에 대한 쿼리를 작성해야한다.

어떤 제안을 주셔서 감사합니다.

해결법

  1. ==============================

    1.다만 그 방법에 @query 주석을 사용합니다.

    다만 그 방법에 @query 주석을 사용합니다.

    public interface CustomRepository extends MongoRepository<PracticeQuestion, String> {
    
        @Query(value = "{ 'userId' : ?0, 'questions.questionID' : ?1 }", fields = "{ 'questions.questionID' : 1 }")
        List<PracticeQuestion> findByUserIdAndQuestionsQuestionID(int userId, int questionID);
    
    }
    

    @query 주석의 필드 부분을 추가하면이 몽고를 말하고있다 만 문서의 일부를 반환합니다. 당신이 지정하지 않은 모든 누락 -, 그것은 여전히 ​​같은 형식으로 문서 전체를 반환하지만 조심하십시오. 코드가 여전히 목록 을 반환해야 할 것이다 그래서 당신은해야 할 것 :

    foreach (PracticeQuestion pq : practiceQuestions) {
        Question q = pq.getQuestions().get(0); // This should be your question.
    }
    
  2. ==============================

    2.속성 식

    속성 식

    앞의 예에서와 같이 속성 식 만 관리되는 개체의 직접적인 속성을 참조 할 수 있습니다. 쿼리 생성 시간에 당신은 이미 구문 분석 된 속성은 관리되는 도메인 클래스의 속성입니다 있는지 확인하십시오. 그러나, 당신은 또한 중첩 된 속성을 통과하여 제약 조건을 정의 할 수 있습니다. 가정 사람이 된 우편 번호와 주소가 있습니다. 그런 경우에서 <이용시> 방법 이름 findByAddressZipCode (우편 번호 우편 번호); 속성 탐색 x.address.zipCode을 만듭니다. 해상도 알고리즘은 그 이름 (uncapitalized)와 속성의 속성과 같은 검사 도메인 클래스 전체 부분 (AddressZipCode)를 해석하기 시작한다. 알고리즘이 성공하면 그것은 그 속성을 사용합니다. 그렇지 않은 경우, 알고리즘은 우리의 예를 들어, AddressZip 및 코드에서 해당 속성을 찾기 위해 머리에 오른쪽에서 낙타 케이스 부분과 꼬리 시도에서 소스를 분할합니다. 알고리즘이 그 머리와 속성을 발견하는 경우가 꼬리를 소요하고 거기에서 나무 아래를 구축 계속 분할은 방법으로 꼬리는 단지 설명했다. 첫 번째 분할이 일치하지 않는 경우, 알고리즘은 왼쪽 (주소, 우편 번호) 및 계속에 스플릿 포인트를 이동합니다.

    이것은 대부분의 경우에 작동해야하지만 알고리즘이 잘못 속성을 선택하는 것이 가능합니다. Person 클래스는 addressZip 속성이뿐만 아니라 가정하자. 이 알고리즘은 이미 첫 번째 분할 라운드에서 일치 본질적으로 잘못된 속성을 선택하고 (addressZip의 종류는 아마 더 코드 속성이 없기 때문에) 결국 실패합니다. 수동 탐색 지점을 정의에 메소드 이름 안에 _ 사용이 모호성을 해결합니다. 그래서 우리의 메소드 이름과 같이 끝낼 것이다 :

    사용자 데이터 저장소 :

    List<UserData> findByAddress_ZipCode(ZipCode zipCode);
    
    UserData findByUserId(String userId);
    

    ProfileRepository :

    Profile findByProfileId(String profileId);
    

    UserData를 RepositoryImpl :

    UserData userData =  userDateRepository.findByUserId(userId);
    
    Profile profile = profileRepository.findByProfileId(userData.getProfileId());
    
    userData.setProfile(profile);
    

    노래를 곡 샘플 :

    public class UserData {
    
        private String userId;
        private String status;
        private Address address;
        private String profileId;
    
        //New Property
        private Profile profile;
    
        //TODO:setter & getter
    }
    
    public class Profile {
    
        private String email;
        private String profileId;
    }
    

    저장소 클래스의 문서 / POJO 위의 경우 :

    UserData를 findByProfile_Email (문자열 이메일);

    이 타이밍 : http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

  3. ==============================

    3.당신은 몽고 집계 프레임 워크를 사용합니다 :

    당신은 몽고 집계 프레임 워크를 사용합니다 :

    1) 몽고 저장소에 사용자 정의 메소드를 만듭니다 저장소에 사용자 지정 방법을 추가

    UnwindOperation unwind =  Aggregation.unwind("questions");
    MatchOperation match = Aggregation.match(Criteria.where("userId").is(userId).and("questions.questionId").is(questionID));
    Aggregation aggregation = Aggregation.newAggregation(unwind,match);
    AggregationResults<PracticeQuestionUnwind> results = mongoOperations.aggregate(aggregation, "PracticeQuestion",
                    PracticeQuestionUnwind.class);
    return results.getMappedResults();
    

    2) 당신은 언 와인드 작업이 아래와 같이) 클래스 구조를 변경하기 때문에 (클래스를 작성해야합니다 :

    public class PracticeQuestionUnwind {
        private String userId;
        private Question questions;
    

    이것은 당신에게 제공하는 사용자 ID와 questionId 일치하는 경우에만 그 결과를 줄 것이다

    1 questionId : userId를 검색 결과 111 :

    {
        "userId": "1",
         "questions": {
                    "questionId": "111",
                    "type": "optional"
                 }
     }
    
  4. from https://stackoverflow.com/questions/12730370/spring-data-mongodb-findby-method-for-nested-objects by cc-by-sa and MIT license