在MongoDB中自动递增序列字段时插入文档

时间:2018-03-26 21:03:36

标签: c# mongodb

问题陈述:

我在MongoDB中有一个集合,其字段的类型为Int32。我想在这个集合中添加一个文档。我需要为每个插入值增加1,因为该字段已编入索引并且必须是唯一的。

选项:

  1. [preferred]增加DB端的值。也就是说,不指定新的(更高)值。只需指示MongoDB在插入时自动递增。
  2. 先读。对DB执行查找查询,首先查找当前(插入前)最高值,在内存中递增,然后插入新文档。这可能由于比赛条件而失败(操作不是原子的)。
  3. 将索引计数器保留在内存中。对我来说不是一个选项,因为有多个应用程序写入同一个集合(传统限制)。
  4. 其他想法?
  5. 示例:

    {
        _id: ....
        index: 123,
        open: true
    }
    
     await collection.InsertOneAsync(record.ToBsonDocument());
    

    插入的新文档的索引值应为124

    语言:

    C#

    问题:

    您能提供示例代码(C#)来实现第一个选项吗?

    额外信息:

    我无法访问其他应用程序的代码(保留自己的索引号)。因此,使用另一个集合并添加序列解析器功能将无法工作,因为这将触发对旧版应用程序的更改。

3 个答案:

答案 0 :(得分:0)

您可以在单独的集合counter

中创建Mongo序列
db.counter.insert({ _id: "mySeq", seq: 0 })

您可以将序列逻辑封装在一个简单的function中,就像这样

function getNextMySeq(name) {
    var ret = db.counter.findAndModify({
        query: { _id: name },
        update: { $inc: { seq: 1 } },
        new: true
    });
    return ret.seq;
}

现在只需在插入期间使用函数调用

db.collection.insert({
  index: getNextMySeq("mySeq") 
})

答案 1 :(得分:0)

MongoDB有一个关于如何实现here

的默认教程

1 - 创建一个计数器集合并在其中插入id:

db.counters.insert(
   {
      _id: "userid",
      seq: 0
   }
)

2 - 创建自定义函数以检索下一个值:

function getNextSequence(name) {
   var ret = db.counters.findAndModify(
          {
            query: { _id: name },
            update: { $inc: { seq: 1 } },
            new: true
          }
   );

   return ret.seq;
}

使用getNextSequence检索下一个值:

db.users.insert(
   {
     _id: getNextSequence("userid"),
     name: "Sarah C."
   }
)

db.users.insert(
   {
     _id: getNextSequence("userid"),
     name: "Bob D."
   }
)

答案 2 :(得分:0)

我必须在使用MongoDB C#驱动程序的项目中执行此操作。

这就是我所做的:我创建了一个名为Sequence的单独集合,并带有其名称和值,并且还为其创建了一个存储库。

这是Sequence类的代码:

public class Sequence
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonElement("_id")]
    public string Id { get; set; }

    public string SequenceName { get; set; }

    public int SequenceValue { get; set; }
}

现在是生成序列值的方法的代码:

public class SequenceRepository
{
    protected readonly IMongoDatabase _database;
    protected readonly IMongoCollection<Sequence> _collection;

    public SequenceRepository(IMongoDatabase database)
    {
        _database = database;
        _colecao = _database.GetCollection<Sequence>(typeof(Sequence).Name);
    }

    public int GetSequenceValue(string sequenceName)
    {
        var filter = Builders<Sequence>.Filter.Eq(s => s.SequenceName, sequenceName);
        var update = Builders<Sequence>.Update.Inc(s => s.SequenceValue , 1);

        var result = _colecao.FindOneAndUpdate(filtrer, update, new FindOneAndUpdateOptions<Sequence, Sequence> { IsUpsert = true, ReturnDocument = ReturnDocument.After });

        return result.SequenceValue;
    }
}

最后我在插入一些文档之前调用了此方法:

public void Inserir(Order order)
{
    order.Code = new SequenceRepository(_database).GetSequenceValue("orderSequence");

    _collection.InsertOne(order);
}