codememo

스프링 데이터 - Mongodb - 내포된 객체에 대한 방법으로 찾기

tipmemo 2023. 6. 22. 21:54
반응형

스프링 데이터 - Mongodb - 내포된 객체에 대한 방법으로 찾기

두 개의 도메인 객체를 가지고 있습니다.

@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"
        }
    ]
}

userId와 questionId를 기반으로 "type"을 업데이트해야 하므로 사용자 지정 Repository 인터페이스 내에 findBy 쿼리 방법을 작성했습니다.

public interface CustomRepository extends MongoRepository<PracticeQuestion, String> {

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

제 문제는 userId를 1로 하고 질문을 하면서 이 메서드를 실행할 때입니다.ID가 3인 경우, 질문과 상관없이 전체 질문 목록을 반환합니다.ID. 쿼리 메서드 이름이 유효한지 또는 중첩된 개체에 대한 쿼리를 작성하는 방법입니다.

제안해 주셔서 감사합니다.

사용하기만 하면 됩니다.@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);

}

추가를 통해fields의 일부@Query주석, 당신은 Mongo에게 문서의 그 부분만 반환하라고 말하고 있습니다.그러나 지정하지 않은 모든 내용이 누락된 동일한 형식으로 전체 문서를 반환합니다.그래서 당신의 코드는 여전히 되돌아와야 합니다.List<PracticeQuestion>그리고 당신은 다음을 해야 할 것입니다.

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

속성 식

속성 표현식은 앞의 예와 같이 관리 엔티티의 직접 속성만 나타낼 수 있습니다.쿼리를 만들 때 이미 구문 분석된 속성이 관리 도메인 클래스의 속성인지 확인해야 합니다.그러나 중첩된 특성을 통과하여 제약 조건을 정의할 수도 있습니다.개인이 우편 번호가 있는 주소를 가지고 있다고 가정합니다.이 경우 메서드 이름:List<Person> findByAddressZipCode(ZipCode zipCode);traversal x.address.zipCode 속성을 생성합니다.확인 알고리즘은 전체 부품(AddressZipCode)을 속성으로 해석하는 것으로 시작하여 도메인 클래스에서 해당 이름(자본화되지 않음)의 속성을 확인합니다.알고리즘이 성공하면 해당 속성을 사용합니다.그렇지 않은 경우, 이 알고리즘은 낙타 케이스 부품의 소스를 오른쪽에서 머리와 꼬리로 분할하고 해당 속성(예: AddressZip 및 Code)을 찾습니다.알고리즘이 해당 머리를 가진 속성을 찾으면 꼬리를 사용하여 트리를 아래로 계속 구축하고 방금 설명한 방식으로 꼬리를 분할합니다.첫 번째 분할이 일치하지 않으면 알고리즘이 분할 지점을 왼쪽(주소, ZipCode)으로 이동하고 계속합니다.

대부분의 경우 이 방법이 사용 가능하지만 알고리즘이 잘못된 속성을 선택할 수 있습니다.사용자 클래스에도 addressZip 속성이 있다고 가정합니다.알고리즘이 첫 번째 분할 라운드에서 이미 일치하고 기본적으로 잘못된 속성을 선택하여 마지막으로 실패합니다(주소 유형 Zip에 코드 속성이 없을 수 있음).이 모호성을 해결하려면 메서드 이름 내부에 _를 사용하여 통과점을 수동으로 정의할 수 있습니다.그래서 우리의 메소드 이름은 다음과 같습니다.

사용자 데이터 리포지토리:

List<UserData> findByAddress_ZipCode(ZipCode zipCode);

UserData findByUserId(String userId);

프로필 리포지토리:

Profile findByProfileId(String profileId);

사용자 데이터 리포지토리 임플:

UserData userData =  userDateRepository.findByUserId(userId);

Profile profile = profileRepository.findByProfileId(userData.getProfileId());

userData.setProfile(profile);

Pojo 표본:

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의 경우:

사용자 데이터 findByProfile_Email(문자열 전자 메일);

참고 자료: http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

Mongo Aggregation 프레임워크를 사용해야 합니다.

mongo 리포지토리에 대한 사용자 정의 메서드 만들기 : 리포지토리에 사용자 정의 메서드 추가

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

다음과 같이 클래스를 생성해야 합니다(풀기 작업으로 인해 클래스 구조가 변경되었기 때문).

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

제공된 됩니다.userId그리고.questionId

userId 1 및 questionId 111에 대한 결과:

{
    "userId": "1",
     "questions": {
                "questionId": "111",
                "type": "optional"
             }
 }

저도 비슷한 문제가 있었습니다.중첩된 클래스 속성 앞에 $를 추가했습니다.의심할 여지 없이 시도해 보다

@Query(value = "{ 'userId' : ?0, 'questions.$questionID' : ?1 }") List<PracticeQuestion> findPracticeQuestionByUserIdAndQuestionsQuestionID(int userId, int questionID);

언급URL : https://stackoverflow.com/questions/12730370/spring-data-mongodb-findby-method-for-nested-objects

반응형