使用 MongoDB .Net 驱动程序查找 POCO
Find POCO with MongoDB .Net driver
MongoDB 比我记忆中的要难!我已经尝试了各种版本的 if-exists-replace-else-insert 的各种功能和选项。应该很容易,不是吗?
我个人认为以下应该有效。
var collection = storageClient.GetCollection<Observer>("observers");
await collection.Indexes.CreateOneAsync(Builders<Observer>.IndexKeys.Ascending(_ => _.MyId), new CreateIndexOptions { Unique = true });
foreach (var observer in _observers)
{
observer.Timestamp = DateTime.Now;
var res = await collection.FindAsync(o => o.MyId == observer.MyId);
if (res==null ||res.Current == null) {
await collection.InsertOneAsync(observer); //Part 1, fails 2nd time solved with res.MoveNextAsync()
}
else
{
observer.ID = res.Current.Single().ID;
var res2 = await collection.ReplaceOneAsync(o=>o.MyId==observer.MyId, observer);
var res3 = await collection.FindAsync(o => o.MyId == observer.MyId);
await res3.MoveNextAsync();
Debug.Assert(res3.Current.Single().Timestamp == observer.Timestamp); //Part 2, Assert fails.
}
}
观察者大概长这样:
public class Observer : IObserver
{
[BsonId]
public Guid ID { get; set; }
public int MyId { get; set; }
public DateTime Timestamp { get; set; }
}
我第二次 运行 使用完全相同的集合时,我意外地得到了:
E11000 duplicate key error index: db.observers.$MyId_1 dup key: { : 14040 }
编辑:
添加了原始第二部分代码:替换。
编辑 2:
现在我的代码看起来像这样。仍然失败。
var collection = storageClient.GetCollection<Observer>("gavagai_mentions");
await collection.Indexes.CreateOneAsync(Builders<Observer>.IndexKeys.Ascending(_ => _.MyID), new CreateIndexOptions { Unique = true });
foreach (var observer in _observers)
{
observer.Timestamp = DateTime.Now;
// Create a BsonDocument version of the POCO that we can manipulate
// and then remove the _id field so it can be used in a $set.
var bsonObserver = observer.ToBsonDocument();
bsonObserver.Remove("_id");
// Create an update object that sets all fields on an insert, and everthing
// but the immutable _id on an update.
var update = new BsonDocument("$set", bsonObserver);
update.Add(new BsonDocument("$setOnInsert", new BsonDocument("_id", observer.ID)));
// Enable the upsert option to create the doc if it's not found.
var options = new UpdateOptions { IsUpsert = true };
var res = await collection.UpdateOneAsync(o => o.MyID == observer.MyID,
update, options);
var res2 = await collection.FindAsync(o => o.MyID == observer.MyID);
await res2.MoveNextAsync();
Debug.Assert(res2.Current.Single().Timestamp == observer.Timestamp); //Assert fails, but only because MongoDB stores dates as UTC, or so I deduce. It works!!
}
好的,好久没用游标了。
await res.MoveNextAsync();
有帮助。
这东西不难Google,但事实是,我失败了,所以我要留下这个问题。
如果您对第二部分 有答案,那么我真的很想 post 在这里回答,我很乐意编辑问题。
正如评论中指出的那样,这些信息实际上在文档中很容易获得 http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/crud/reading/#finding-documents。
如果文档尚不存在,您可以使用 IsUpsert
选项创建文档,从而使用 UpdateOneAsync
自动执行此操作。
foreach (var observer in _observers)
{
// Create a BsonDocument version of the POCO that we can manipulate
// and then remove the _id field so it can be used in a $set.
var bsonObserver = observer.ToBsonDocument();
bsonObserver.Remove("_id");
// Create an update object that sets all fields on an insert, and everthing
// but the immutable _id on an update.
var update = new BsonDocument("$set", bsonObserver);
update.Add(new BsonDocument("$setOnInsert", new BsonDocument("_id", observer.ID)));
// Enable the upsert option to create the doc if it's not found.
var options = new UpdateOptions { IsUpsert = true };
var res = await collection.UpdateOneAsync(o => o.MyId == observer.MyId,
update, options);
}
MongoDB 比我记忆中的要难!我已经尝试了各种版本的 if-exists-replace-else-insert 的各种功能和选项。应该很容易,不是吗?
我个人认为以下应该有效。
var collection = storageClient.GetCollection<Observer>("observers");
await collection.Indexes.CreateOneAsync(Builders<Observer>.IndexKeys.Ascending(_ => _.MyId), new CreateIndexOptions { Unique = true });
foreach (var observer in _observers)
{
observer.Timestamp = DateTime.Now;
var res = await collection.FindAsync(o => o.MyId == observer.MyId);
if (res==null ||res.Current == null) {
await collection.InsertOneAsync(observer); //Part 1, fails 2nd time solved with res.MoveNextAsync()
}
else
{
observer.ID = res.Current.Single().ID;
var res2 = await collection.ReplaceOneAsync(o=>o.MyId==observer.MyId, observer);
var res3 = await collection.FindAsync(o => o.MyId == observer.MyId);
await res3.MoveNextAsync();
Debug.Assert(res3.Current.Single().Timestamp == observer.Timestamp); //Part 2, Assert fails.
}
}
观察者大概长这样:
public class Observer : IObserver
{
[BsonId]
public Guid ID { get; set; }
public int MyId { get; set; }
public DateTime Timestamp { get; set; }
}
我第二次 运行 使用完全相同的集合时,我意外地得到了:
E11000 duplicate key error index: db.observers.$MyId_1 dup key: { : 14040 }
编辑:
添加了原始第二部分代码:替换。
编辑 2:
现在我的代码看起来像这样。仍然失败。
var collection = storageClient.GetCollection<Observer>("gavagai_mentions");
await collection.Indexes.CreateOneAsync(Builders<Observer>.IndexKeys.Ascending(_ => _.MyID), new CreateIndexOptions { Unique = true });
foreach (var observer in _observers)
{
observer.Timestamp = DateTime.Now;
// Create a BsonDocument version of the POCO that we can manipulate
// and then remove the _id field so it can be used in a $set.
var bsonObserver = observer.ToBsonDocument();
bsonObserver.Remove("_id");
// Create an update object that sets all fields on an insert, and everthing
// but the immutable _id on an update.
var update = new BsonDocument("$set", bsonObserver);
update.Add(new BsonDocument("$setOnInsert", new BsonDocument("_id", observer.ID)));
// Enable the upsert option to create the doc if it's not found.
var options = new UpdateOptions { IsUpsert = true };
var res = await collection.UpdateOneAsync(o => o.MyID == observer.MyID,
update, options);
var res2 = await collection.FindAsync(o => o.MyID == observer.MyID);
await res2.MoveNextAsync();
Debug.Assert(res2.Current.Single().Timestamp == observer.Timestamp); //Assert fails, but only because MongoDB stores dates as UTC, or so I deduce. It works!!
}
好的,好久没用游标了。
await res.MoveNextAsync();
有帮助。
这东西不难Google,但事实是,我失败了,所以我要留下这个问题。
如果您对第二部分 有答案,那么我真的很想 post 在这里回答,我很乐意编辑问题。
正如评论中指出的那样,这些信息实际上在文档中很容易获得 http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/crud/reading/#finding-documents。
如果文档尚不存在,您可以使用 IsUpsert
选项创建文档,从而使用 UpdateOneAsync
自动执行此操作。
foreach (var observer in _observers)
{
// Create a BsonDocument version of the POCO that we can manipulate
// and then remove the _id field so it can be used in a $set.
var bsonObserver = observer.ToBsonDocument();
bsonObserver.Remove("_id");
// Create an update object that sets all fields on an insert, and everthing
// but the immutable _id on an update.
var update = new BsonDocument("$set", bsonObserver);
update.Add(new BsonDocument("$setOnInsert", new BsonDocument("_id", observer.ID)));
// Enable the upsert option to create the doc if it's not found.
var options = new UpdateOptions { IsUpsert = true };
var res = await collection.UpdateOneAsync(o => o.MyId == observer.MyId,
update, options);
}