2012-10-04 13 views
11

Mam dwa obiekty domeny,wiosna - MongoDB - findBy Metoda zagnieżdżonych obiektów

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

Moje JSON doc jest tak,

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

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

muszę zaktualizować "typ" w oparciu o identyfikatora użytkownika i questionId, więc napisałem findBy metodę zapytania wewnątrz interfejsu zwyczaj repozytorium

public interface CustomRepository extends MongoRepository<PracticeQuestion, String> { 

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

Mój problem jest kiedy wykonuję tę metodę z identyfikatorem użytkownika jako 1 i questionID jako 3, zwraca całą listę pytań niezależnie od pytania. Czy nazwa metody zapytania jest prawidłowa lub jak powinienem napisać zapytanie dla zagnieżdżonych obiektów.

Dzięki za wszelkie sugestie.

Odpowiedz

14

Po prostu użyj adnotacji @Query dla tej metody.

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

} 

Dodając fields części @Query adnotacji, mówisz Mongo tylko powrócić do tej części dokumentu. Pamiętaj jednak, że nadal zwraca cały dokument w tym samym formacie - po prostu brakuje wszystkiego, czego nie określiłeś. Więc twój kod będzie jeszcze musiał wrócić List<PracticeQuestion> i trzeba będzie zrobić:

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

Dzięki za odpowiedz, ale znowu ta kwerenda zwraca array, a nie odpowiedni element w tablicy. – user1720083

+1

Oh. Rozumiem, co masz na myśli. Możesz tylko zwrócić cały dokument. Zapytanie faktycznie szuka dokumentów, które mają ten questionID. Ale zawsze dostajesz cały dokument - nigdy nie tylko pytanie. To nie jest java, to sprawa MongoDB.Popatrz na to pytanie/odpowiedź w celu wyjaśnienia: http://stackoverflow.com/a/3985982/229178 – sbzoom

+1

Po kilku zadaniach domowych zdałem sobie sprawę, że możesz określić częściowe obiekty w części "pola" zapytania ("projekcje"). http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+ofields Zaktualizuję powyższą odpowiedź, aby podać przykład. – sbzoom

5

Property wyrażenia

wyrażenia nieruchomość może odnosić się tylko do bezpośredniego majątku zarządzanego podmiotu, jak pokazano w poprzednim przykładzie. W momencie tworzenia zapytania upewniłeś się, że parsowana właściwość jest własnością zarządzanej klasy domeny. Można jednak również definiować wiązania, przechodząc przez zagnieżdżone właściwości. Załóżmy, że osoby mają adresy z kodami Zip. W takim przypadku nazwa metody:

List findByAddressZipCode (Kod pocztowy ZipCode); tworzy właściwość traversal x.address.zipCode. Algorytm rozdzielczości rozpoczyna się od interpretacji całej części (AddressZipCode) jako właściwości i sprawdza klasę domeny dla właściwości o tej nazwie (bezapisu). Jeśli algorytm się powiedzie, użyje tej właściwości. Jeśli nie, algorytm dzieli źródło na części wielbłąda z prawej strony na głowę i ogon i próbuje znaleźć odpowiednią właściwość, w naszym przykładzie, adresZip i kod. Jeśli algorytm znajdzie właściwość z tą głową, bierze ogon i dalej buduje drzewo stamtąd, dzieląc ogon w opisany sposób. Jeśli pierwszy podział się nie zgadza, algorytm przesuwa punkt podziału w lewo (adres, kod pocztowy) i kontynuuje.

Mimo że powinno to działać w większości przypadków, algorytm może wybrać niewłaściwą właściwość. Załóżmy, że klasa Person ma również właściwość addressZip. Algorytm byłby zgodny już w pierwszej rundzie podziału i zasadniczo wybiera niewłaściwą właściwość i ostatecznie kończy się niepowodzeniem (ponieważ typ adresuZip prawdopodobnie nie ma właściwości code). Aby rozwiązać tę niejednoznaczność, możesz użyć _ wewnątrz nazwy metody, aby ręcznie zdefiniować punkty przejścia.Więc nasza nazwa metody skończy się tak:

UserDataRepository:

Lista findByAddress_ZipCode (KodPocztowy kod pocztowy);

UserData findByUserId (String userId);

ProfileRepository:

profilu findByProfileId (String ProfileID);

UserDataRepositoryImpl:

UserData userData = userDateRepository.findByUserId (userId);

Profil profilu = profileRepository.findByProfileId (userData.getProfileId());

userData.setProfile (profil);

Próbka 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 profilu {

private String email; 
private String profileId; 

}

Dla powyższego dokumentu/POJO w klasie repozytorium:

UserData findByProfile_Email (String email);

Dla Ref: http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

0

trzeba użyć Mongo Aggregation ramowa:

1) Utwórz niestandardową metodę do repozytorium Mongo: Add custom method to Repository

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) Trzeba cretae klasę (Ponieważ operacja rozwijania zmieniła strukturę klas), jak poniżej:

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

To daje tylko te wyniki, które pasuje do zapewnienia userId i questionId

Wynik dla userid: 1 i questionId: 111:

{ 
    "userId": "1", 
    "questions": { 
       "questionId": "111", 
       "type": "optional" 
      } 
} 
Powiązane problemy