2015-05-19 15 views
5

Używam stosu Średnia. Czuję się nieswojo w tym nowym i mam się w marynacie. Widziałem przykłady aktualizowania rekordów za pomocą set lub push, ale ponieważ próbuję zaktualizować jeden obiekt Json wewnątrz obiektu json w tablicy obiektów json mam problemy.MongoDB. Jak zaktualizować właściwość json wewnątrz tablicy

Rozważmy następujący schematu

token: { 
    type: String, 
    required: "FB access token required." 
}, 
fbId: { 
    type: String, 
    required: "FB id required.", 
    unique: true 
}, 
accounts: { 
    type: Array, 
    default: [] 
} 

Moje konta tablica składa się z obiektów JSON z których każdy wygląda tak:

{ 
    "name": "some name", 
    "credentials": { 
     "username": "some username", 
     "password": "some password" 
} 

Próbuję aktualizowanie kont każdym razem, gdy użytkownik dodaje nowy. Tak więc w tym przypadku mogę użyć $ push w porządku. Ale nie chcę duplikatów nazw, a $ push nie działa tutaj. Więc próbowałem użyć $ set, ale $ set nie wstawia obiektów z nowymi nazwami do kont. Więc próbowałem użyć upsert: true z $ set, ale teraz otrzymuję podwójne błędy.

Oto przykład, w którym próbuję zindeksować nazwę na kontach. Zakładam, że trochę zawracam sobie pytanie.

var name = "some name"; 
var fbId = "some fb Id"; 
var token = "some token"; 
var username = "some other username"; 
var password = "some other password"; 

var query = { 
    fbId: fbId, 
    token: token, 
    "accounts.name":name 
}; 
var update = { 
    $set: { 
     accounts: [{ 
      name: name, 
      credentials: { 
       username: username, 
       password: password 
      } 
     }] 
    } 

}; 
var options = { 
    upsert: true 
}; 
User.update(query, update, options, 
    function (err, numberAffected, rawResponse) { 
     //handle it 
    }); 
); 

Podsumowując moje pytanie, czy rozsądnie jest myśleć, że mogę zaktualizować to jednym połączeniem, a jeśli tak, to w jaki sposób? Czy powinienem znaleźć obiekt, wymienić jego wartości, a następnie ponownie umieścić w bazie danych?

Odpowiedz

4

Można użyć operatora aktualizacji $ tablicy:

var query = { 
    fbId: fbId, 
    token: token, 
    "accounts.name":name 
}; 
var update = { 
    $set: { 
     "accounts.$": [{  //The $ operator goes into the update object 
      name: name, 
      credentials: { 
       username: username, 
       password: password 
      } 
     }] 
    } 
}; 

Według documentation:

pozycyjna $ Operator identyfikuje element w tablicy aktualizacji bez jawne określanie położenia elementu w tablicy .

EDIT:

Według tego MongoDB JIRA page korzystając upsert z operatorem $ pozycyjnej jest nadal kwestią otwartą.

Przeszukałem i znalazłem możliwe rozwiązanie, które niestety pokonało twój cel osiągnięcia tego jednym telefonem. Można go znaleźć here.

Podsumowując tę ​​odpowiedź, należy najpierw wysłać zapytanie o aktualizację bez flagi upsert. Następnie sprawdź odpowiedź, aby zobaczyć, czy dokument został zaktualizowany, jeśli nie (oznacza to, że taki dokument nie istnieje), wyślij kolejne zapytanie za pomocą operatora $push, aby wstawić nowy dokument podrzędny do tablicy.

+0

Otrzymywanie następującej odpowiedzi na błąd. Operator pozycyjny nie znalazł dopasowania z zapytania. Nieaktualizowana aktualizacja: konta. $ – zafrani

+0

Och, musisz również ustawić flagę upsert na true. – ZeMoon

+0

To było. Kiedy komentuję flagę upsert, nie dostaję błędów, ale również niczego nie aktualizuję. – zafrani

0

Jeśli dla Ciebie działa $push, ale chcesz uniknąć dodawania duplikatów do tablicy, spróbuj $addToSet. Doda wartość do tablicy, o ile ta wartość nie jest już w niej zawarta. Zapoznaj się z dokumentacją $addToSet.

Aktualizacja

z oryginalnego postu:

Próbuję aktualizowanie kont każdym razem, gdy użytkownik dodaje nowe. Tak więc w tym przypadku mogę użyć $ push w porządku. Ale nie chcę duplikatów nazw, , a wypychanie $ nie powiedzie się tutaj.

var uniqueAccount = { 
    name:'unique account', 
    credentials: { 
    username:'new username', 
    password:'some secret password' 
    } 
}; 

db.accounts.update({fbId: fbId, token: token}, 
    {accounts: {$addToSet: uniqueAccount}}); 
+0

Tak, ale jeśli już istnieje, nie zaktualizuje go. – zafrani

Powiązane problemy