2012-04-15 2 views
2

Ich habe diese Struktur:Wie kann ich eine innere Eigenschaft mit dem 10gen C# -Treiber aktualisieren?

public class User 
{ 
    public ObjectId Id { get; set; } 
    public Location Location { get; set; } 
    public DateTime LastAround {get;set;} 
} 

public class Location 
{ 
    public double Latitude { get; set; } 
    public double Longitude { get; set; } 
} 

ich ein paar Dinge ausprobiert habe, aber ich will User Lage aktualisieren, und wenn sie wurden zuletzt um.

dies versucht:

userHelper.Collection.Update(
    Query.EQ("_id", userId), 
    Update.SetWrapped<Location>("Location", new Location { Latitude = latitude, Longitude = longitude }).Set("LastAround", DateTime.UtcNow)); 

und diese:

userHelper.Collection.Update(
    Query.EQ("_id", userId), 
    Update.Set("Location.Latitude", latitude) 
     .Set("Location.Longitude", longitude) 
     .Set("LastAround", DateTime.UtcNow)); 

nichts funktioniert ... wie kann ich das tun?

-Update 17.04:

userHelper.Collection.Update(
       Query.EQ("_id", new ObjectId(userId)), 
       Update 
        .SetWrapped<Location>("Location", new Location { Longitude = longitude, Latitude = latitude }) 
        .Set("LastAround", DateTime.UtcNow) 
      ); 

Der lng und lat Wert Aufträge scheinen sehr wichtig zu sein, wenn Abfragen auf ihnen zu tun. Ich habe eine Geonear-Abfrage gemacht und einen seltsamen Fehler außerhalb der Grenzen bekommen. Wenn Sie in der falschen Reihenfolge aktualisieren, werden zuerst Lats und dann der Fehler angezeigt.

Antwort

2

Beide ursprünglichen Update-Anweisungen funktionieren sollte, schrieb ich ein kleines Beispielprogramm zu demonstrieren

Nach dieser Insert Anweisung ausführen:.

var userId = ObjectId.GenerateNewId(); 
var user = new User 
{ 
    Id = userId, 
    Location = new Location { Latitude = 1.0, Longitude = 2.0 }, 
    LastAround = new DateTime(2012, 4, 14, 0, 0, 0, DateTimeKind.Utc) 
}; 
collection.Insert(user); 

Das Dokument wie dies in der Mongo Shell sieht :

> db.test.find() 
{ "_id" : ObjectId("4f8c5d33e447ad34b8c7ac84"), "Location" : { "Latitude" : 1, "Longitude" : 2 }, "LastAround" : ISODate("2012-04-14T00:00:00Z") } 
> 

Nach der ersten Form der Update-Anweisung ausführen:

collection.Update(
    Query.EQ("_id", userId), 
    Update 
     .SetWrapped<Location>("Location", new Location { Latitude = 3.0, Longitude = 4.0 }) 
     .Set("LastAround", new DateTime(2012, 4, 15, 0, 0, 0, DateTimeKind.Utc))); 

das Dokument sieht wie folgt aus:

> db.test.find() 
{ "_id" : ObjectId("4f8c5d33e447ad34b8c7ac84"), "Location" : { "Latitude" : 3, "Longitude" : 4 }, "LastAround" : ISODate("2012-04-15T00:00:00Z") } 
> 

und nach der zweiten Form der Update-Anweisung ausführen:

collection.Update(
    Query.EQ("_id", userId), 
    Update 
     .Set("Location.Latitude", 5.0) 
     .Set("Location.Longitude", 6.0) 
     .Set("LastAround", new DateTime(2012, 4, 16, 0, 0, 0, DateTimeKind.Utc))); 

das Dokument wie folgt aussieht:

> db.test.find() 
{ "_id" : ObjectId("4f8c5d33e447ad34b8c7ac84"), "Location" : { "Latitude" : 5, "Longitude" : 6 }, "LastAround" : ISODate("2012-04-16T00:00:00Z") } 
> 

So Die beiden Formen der Update-Anweisung funktionieren.hier

Das vollständige Programm ist:

http://www.pastie.org/3799469

+0

Komisch, ich habe keine Ahnung, warum meine nicht funktionierte. Ich habe gelernt, obwohl die für Geo-Abfragen die lat und lng müssen Positionen zu wechseln mit dem lng zuerst. – rball

0

Ihre beiden Alternativen sehen gut aus.

Sind Sie sicher, dass Ihre userId-Variable den richtigen Wert hatte? Möglicherweise findet das Update kein übereinstimmendes zu aktualisierendes Dokument.

+0

Ja, es sah alles ok. Die Update-Anweisung konnte jedoch nicht funktionieren. – rball

+0

Ich habe eine neue Antwort mit einem Beispielcode gestartet. –

+0

Wenn Ihre userId-Variable vom Typ string war und Sie sie nicht in eine ObjectId im Aufruf von Query.EQ konvertiert haben, dann hätte Find das übereinstimmende Dokument nicht gefunden (da eine Zeichenfolge nicht mit einer ObjectId übereinstimmen kann). Es scheint also wahrscheinlich, dass Ihr Update das Update nicht durchgeführt hat, weil die Abfrage keinem Dokument entspricht. –

0

Was ich am Ende tun:

var userHelper = new MongoHelper<User>(); 
ObjectId id = new ObjectId(userId); 
var user = userHelper.Collection.FindAll().Where(u => u.Id == id).Single(); 
user.LastAround = DateTime.UtcNow; 
user.Location = new Location { Longitude = longitude, Latitude = latitude }; 
userHelper.Collection.Save(user); 

die funktioniert. Nicht sicher, warum der andere Weg nicht würde. Ich nehme an, das ist mehr "SQL" wie, obwohl vielleicht nicht die beste Leistung haben. . :(

+0

Es gibt ein Problem mit diesem Code, da FindAll * alle * Dokumente vom Server zurückgibt und Sie dann eine Client-Seite verwenden, auf der Sie die Datei finden, die Sie aktualisieren möchten. Siehe die neue Antwort, die ich mit Beispielcode gestartet habe. –

+0

Das FindAll ist nicht IQueryable? Wie würde ich diesen Befehl dann in anderen Fällen richtig machen? In jedem Fall werde ich versuchen, es zu wechseln, wenn ich heute Abend nach Hause komme. Ich habe deine Antworten bis heute nicht gesehen. – rball

+0

FindAll ist IEnumerable, daher wird die Where-Klausel clientseitig ausgeführt. Sie können eine Abfrage mit Query.EQ ("_ id", id) erstellen und als Argument an Find übergeben. Oder Sie können collection.AsQueryable () aufrufen. Wo (u => u.Id = id) LINQ zu MongoDB verwenden. –

Verwandte Themen