2015-07-16 23 views
10

EDIT: Non cercando il modo javascript per farlo. Sto cercando il modo di farlo con il driver MongoDB C# 2.0 (so che potrebbe non essere possibile, ma spero che qualcuno conosca una soluzione).Elemento Mongo update array (driver .NET 2.0)

Sto cercando di aggiornare il valore di un elemento incorporato in un array sul documento principale nel mio mongodb.

Sto cercando un modo fortemente digitato per farlo. Sto usando il Mongodb c# 2.0 driver

Posso farlo scoccando l'elemento, aggiornando il valore, quindi reinserendolo. Questo non sembra giusto; dal momento che sto sovrascrivendo quello che potrebbe essere stato scritto nel frattempo.

Ecco quello che ho provato finora, ma senza fortuna:

private readonly IMongoCollection<TempAgenda> _collection; 

void Main() 
{ 
    var collectionName = "Agenda"; 
    var client = new MongoClient("mongodb://localhost:27017"); 
    var db = client.GetDatabase("Test"); 
    _collection = db.GetCollection<TempAgenda>(collectionName); 
    UpdateItemTitle(1, 1, "hello"); 
} 

public void UpdateItemTitle(string agendaId, string itemId, string title){ 
    var filter = Builders<TempAgenda>.Filter.Eq(x => x.AgendaId, agendaId); 
    var update = Builders<TempAgenda>.Update.Set(x => x.Items.Single(p => p.Id.Equals(itemId)).Title, title); 
    var result = _collection.UpdateOneAsync(filter, update).Result; 
} 
+0

possibile duplicato di [MongoDB - aggiornare un oggetto in Array nidificato] (http://stackoverflow.com/questions/10522347/mongodb-update-an-object- in-nested-array) –

+0

@BlakesSeven che non è domanda # ac? –

+0

È ancora lo stesso principio. Abbina l'elemento dell'array nella parte della query e usa l'operatore posizionale '$' nella porzione di aggiornamento. Non l'ho tirato fuori casualmente da una borsa. –

risposta

30

Mi ha portato un po 'per capirlo in quanto non sembra essere menzionato in qualsiasi della documentazione ufficiale (o in qualsiasi altro). Ho comunque trovato this sul loro tracker dei problemi, che spiega come utilizzare l'operatore posizionale $ con il driver C# 2.0.

Questo dovrebbe fare quello che vuoi:

public void UpdateItemTitle(string agendaId, string itemId, string title){ 
    var filter = Builders<TempAgenda>.Filter.Where(x => x.AgendaId == agendaId && x.Items.Any(i => i.Id == itemId)); 
    var update = Builders<TempAgenda>.Update.Set(x => x.Items[-1].Title, title); 
    var result = _collection.UpdateOneAsync(filter, update).Result; 
} 

notate che il vostro clausola Item.Single() è stato modificato per Item.Any() e si è trasferito alla definizione del filtro.

[-1] o .ElementAt(-1) è apparentemente trattato appositamente (realtà tutto < 0) e verrà sostituito con l'operatore posizionale $.

È possibile che questo sarà tradotto a questa domanda:

db.Agenda.update({ AgendaId: 1, Items.Id: 1 }, { $set: { Items.$.Title: "hello" } }) 
+0

Ci scusiamo per essere così lenti ad accettare la tua risposta . Funziona molto bene. Sfortunatamente non supportano più di un selettore operativo: https://jira.mongodb.org/browse/SERVER-831 Sembra strano per me, dal momento che questo può essere usato per rendere un migliore isolamento dell'aggiornamento necessario da fare. –

+0

Grazie Søren. Devo dire che non sono un fan della sintassi che hanno scelto anche perché significa che non puoi usare IEnumerable o ICollection e ti costringe a usare il più ingombrante IList o un semplice array – Buvy

+0

@Buvy Dovresti essere in grado di usare il Anche il metodo di estensione LINQ 'ElementAt (-1)'. –

1

Grazie, questo è stato utile. Ho un'aggiunta però, ho usato il precedente per gli array, spingendo verso un array annidato e tirando da uno. Il problema che ho riscontrato è che se avessi un array int (quindi non un oggetto, solo un semplice array int) che il PullFilter non ha funzionato - "Impossibile determinare le informazioni di serializzazione" che è strano in quanto è solo un array di ints. Quello che ho finito è stato renderlo un array di oggetti con un solo parametro int, e tutto ha iniziato a funzionare. Forse un insetto, o forse la mia mancanza di comprensione. Ad ogni modo, dato che ho faticato a trovare informazioni su come tirare e spingere gli array di oggetti nidificati con il driver C# 2.0, ho pensato di pubblicare i miei risultati qui, poiché usano la sintassi sopra riportata.

var filter = Builders<MessageDto>.Filter.Where(x => x._id == entity.ParentID && x.NestedArray.Any(i => i._id == entity._id)); 
var update = Builders<MessageDto>.Update.PullFilter(x => x.NestedArray.ElementAt(-1).User, Builders<User>.Filter.Eq(f => f.UserID, userID)); 
Collection<MessageDto>(currentUser).UpdateOneAsync(filter, update); 

E anche:

var filter = Builders<MessageDto>.Filter.Where(x => x._id == entity.ParentID && x.NestedArray.Any(i => i._id == entity._id)); 
var update = Builders<MessageDto>.Update.Push(x => x.NestedArray.ElementAt(-1).Users, new User { UserID = userID }); 
Collection<MessageDto>(currentUser).UpdateOneAsync(filter, update); 
Problemi correlati