2015-11-14 11 views
9

Próbuję uzyskać objectID obiektu, że mam zaktualizowanego - to jest mój kod Java za pomocą sterownika Java:kierowca Java: jak uzyskać objectID z zaktualizowanym obiektu metodą MongoDB za updateFirst

Query query = new Query(); 
    query.addCriteria(Criteria.where("color").is("pink")); 
    Update update = new Update(); 
    update.set("name", name); 
    WriteResult writeResult = mongoTemplate.updateFirst(query, update, Colors.class); 

    Log.e("object id", writeResult.getUpsertedId().toString()); 

Komunikat dziennika zwraca wartość null. Używam serwera Mongo 3.0 na mongolabie, ponieważ jestem na wolnym poziomie, więc nie powinien zwracać wartości null. Moja Mongo powłoka jest również:

MongoDB wersja shell: 3.0.7

Czy istnieje prosty sposób, aby powrócić identyfikator obiektu dla dokumentu, który właśnie zaktualizowaną? Jaki jest sens metody getUpsertedId(), jeśli nie mogę zwrócić upsertedId?

Aby zrobić to, co chcę, obecnie mam wydać dwie kwerendy, która jest bardzo uciążliwa:

//1st query - updating the object first 
    Query query = new Query(); 
    query.addCriteria(Criteria.where("color").is("pink")); 
    Update update = new Update(); 
    update.set("name", name); 
    WriteResult writeResult = mongoTemplate.updateFirst(query, update, Colors.class); 
    //2nd query - find the object so that I can get its objectid 
    Query queryColor = new Query(); 
    queryColor.addCriteria(Criteria.where("color").is("pink")); 
    queryColor.addCriteria(Criteria.where("name").is(name)); 
    Color color = mongoTemplate.findOne(queryColor, Color.class); 
    Log.e("ColorId", color.getId()); 

Jak na odpowiedź Dawida Próbowałem nawet jego sugestię, aby raczej używać upsert na szablonie, więc zmieniłem kod do dołu i nadal nie działa:

Query query = new Query(); 
    query.addCriteria(Criteria.where("color").is("pink")); 
    Update update = new Update(); 
    update.set("name", name); 
    WriteResult writeResult = mongoTemplate.upsert(query, update, Colors.class); 

    Log.e("object id", writeResult.getUpsertedId().toString()); 

Odpowiedz

6

Simon, myślę, że jest to możliwe w jednym zapytaniu. Potrzebna jest inna metoda o nazwie findAndModify().

W sterowniku java dla mongoDB, ma on metodę o nazwie findOneAndUpdate(filter, update, options).

Ta metoda zwraca dokument, który został zaktualizowany. W zależności od opcji określonych dla tej metody będzie to dokument taki jak przed aktualizacją lub po aktualizacji. Jeśli żaden dokument nie pasuje do filtru zapytania, zostanie zwrócona wartość null. Nie jest wymagane przekazywanie opcji, w takim przypadku zwróci dokument, który został zaktualizowany przed zastosowaniem operacji aktualizacji.

Szybkie spojrzenie na docs sterownik Java mongoTemplate tutaj: http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/FindAndModifyOptions.html mówi mi, że można korzystać z połączenia Metoda:

public <T> T findAndModify(Query query, 
          Update update, 
          FindAndModifyOptions options, 
          Class<T> entityClass) 

Można również zmienić klasę FindAndModifyOptions do podjęcia na zasadzie „upsert”, jeśli element nie znaleziono w zapytaniu. Jeśli zostanie znaleziony, obiekt zostanie po prostu zmodyfikowany.

+0

Byłaby to świetna odpowiedź, gdyby miał przykład;) –

+0

@Markus Dziękuję, sam nie jestem zbyt dobrym facetem z java. Czy możesz edytować odpowiedź, jeśli znasz kod? –

+0

Myślę, że teoretycznie to zadziała, ale nie jestem jeszcze w 100% pewny, ponieważ nie mam czasu, aby go przetestować. Myślę, że wywołanie metody w języku Java byłoby findAndModify: http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html#findAndModify-org .springframework.data.mongodb.core.query.Query-org.springframework.data.mongodb.core.query.Update-org.springframework.data.mongodb.core.FindAndModifyOptions-java.lang.Class- – Simon

1

upsert zastosowanie tylko wtedy, gdy oba

  1. Opcje aktualizacji zostały ustawione na
  2. Nowy dokument został faktycznie utworzony.

Twoje zapytanie nie ma włączonej opcji upsert ani nie tworzy nowego dokumentu. W związku z tym ma sens, że getUpsertedId() zwraca tutaj wartość null.

Niestety nie jest możliwe uzyskanie tego, co chcesz, za pomocą jednego połączenia z bieżącym interfejsem API; musisz podzielić go na dwie rozmowy. Jest to dodatkowo wskazane przez API powłoki Mongo dla WriteResults:

_id dokumentu wstawionego przez upsert. Zwracany tylko wtedy, gdy wynik wyższy o wartość powoduje wstawienie.

+0

Cześć David, nawet jeśli użyłem metody: WriteResult writeResult = mongoTemplate.upsert (zapytanie, aktualizacja, Colors.class); i spróbuj uzyskać identyfikator z getUpsertedId() na nim, nadal nie zwraca id. – Simon

+0

@Simon Wygląda na to, że uruchamiasz upsert na już istniejącym dokumencie, więc to ma sens. Zobacz punkt # 2. Spróbuj zrobić zapytanie 'query.addCriteria (Criteria.where (" color "). Is (" adasdasdsadsa "));' –

+0

Ale w punkcie 1, powiedziałeś, że opcje aktualizacji są włączone. W moim przypadku mongoTemplate ma włączone, więc powinno działać ... Również kod, który zasugerowałeś powyżej, nie miałby sensu, ponieważ wtedy musiałbym utworzyć nowy dokument. Nie tworzę nowego dokumentu, ale właśnie zmieniam mój istniejący dokument przez upsert inaczej, mógłbym łatwo zrobić save i dostać id przez metodę mongoTemplate.save. – Simon

0

To jest przykład to zrobić z findOneAndUpdate (filtr, UPDATE opcji) w Scala:

val findOneAndUpdateOptions = new FindOneAndUpdateOptions 
findOneAndUpdateOptions.returnDocument(ReturnDocument.AFTER) 
val filter = Document.parse("{\"idContrato\":\"12345\"}") 
val update = Document.parse("{ $set: {\"descripcion\": \"New Description\" } }") 
val response = collection.findOneAndUpdate(filter,update,findOneAndUpdateOptions) 
println(response) 
Powiązane problemy