2012-05-22 12 views
7

Mam strukturę obiektu takiego: Modyfikowanie ostatniego elementu tablicy

{ 
    name: "...", 
    pockets: [ 
     { 
      cdate: "....", 
      items: [...] 
     } 
     ... 
    ] 
} 

w operacji aktualizacji, chcę dodać kilka rekordów do przedmiotów polu ostatniej kieszeni elementu. Używanie notacji kropkowej to jedyny znany mi sposób uzyskiwania dostępu do dokumentu podrzędnego, ale nie mogę uzyskać tego, czego chcę. Więc szukam czegoś takie jak:

  • pockets.-1.items
  • pockets.$last.items

Czy jest możliwe aby zmodyfikować ostatni element? Jeśli tak, w jaki sposób?

+0

Czy mam rację, że chcesz zmodyfikować 'items', a nie go pobrać? – paulmelnikow

+0

Tak, masz rację. Podczas pobierania mogę użyć operatora $ slice. – Muatik

+0

Jestem prawie pewien, że nie da się tego zrobić za pomocą prostej aktualizacji, chyba że masz jakiś inny sposób dopasowania ostatniej kieszeni. – paulmelnikow

Odpowiedz

2

Nie wiem, jak to zrobić, używając zapytania jednoliniowego. Ale możesz wybrać rekord, zaktualizować, a następnie zapisać.

var query = <insert query here>; 
var mydocs = db.mycollection.find(query); 
for (var i=0 ; i<mydocs.length ; i++) { 
    mydocs[i].pockets[pockets.length-1].items.push('new item'); 
    db.mycollection.save(mydoc); 
} 
+3

może to nie być bezpieczne dla wątków, ponieważ inny proces mógł zmodyfikować tablicę po znalezieniu i przed zapisaniem. –

+0

@AsyaKamsky doskonały punkt ... Zaktualizuję moją odpowiedź. – McGarnagle

2

Nie sądzę, że można to zrobić atomowo. Istnieje request, aby ta funkcjonalność została dodana do MongoDB.

Jeśli można zapewnić wątku bezpieczeństwa w kodzie aplikacja, prawdopodobnie można użyć sekwencji $ pop z kieszeniami tablicy (który usuwa ostatni element z kieszeni) do zmiennej p a następnie $ addToSet do p.items , teraz możesz wepchnąć p z powrotem do kieszeni. Ale jeśli twoja aplikacja nie ma sposobu, aby zapewnić, że tylko jeden proces może to robić za jednym razem, inny proces może zmodyfikować tablicę w środku tych kroków i może skończyć się utratą tej aktualizacji.

Możesz również zajrzeć do semantyki "Aktualizuj, jeśli aktualna", aby uzyskać inny sposób, w jaki można obejść potencjalny wyścig przez wiele wątków.

Powiązane problemy