MongoDB - самый эффективный способ получить последнюю версию документа - PullRequest
2 голосов
/ 31 января 2012

Я использую MongoDB для хранения коллекции документов.

У каждого документа есть _id (версия), который является ObjectId.Каждый документ имеет идентификатор документа, который используется разными версиями.Это также OjectId, назначенный при создании первого документа.

Какой самый эффективный способ найти самую актуальную версию документа с учетом documentId?

Т.е. я хочучтобы получить запись, где _id = max (_id) и documentId = x

Нужно ли использовать MapReduce?

Заранее спасибо,

Сэм

Ответы [ 2 ]

6 голосов
/ 31 января 2012

Добавить индекс, содержащий оба поля (documentId, _id) и не использовать max (для чего)? Используйте запрос с documentId = x, упорядочьте DESC по _id и limit (1), чтобы получить последние результаты. Помните о правильном порядке сортировки индекса (также DESC)

Нечто подобное

db.collection.find({documentId : "x"}).sort({_id : -1}).limit(1)

Другим подходом (более денормализованным) будет использование другой коллекции с такими документами, как:

{
    documentId : "x",
    latestVersionId : ...
}

Использование атомарных операций позволило бы безопасно обновить эту коллекцию. Добавление правильного индекса сделает запросы быстрыми как молния.

Есть одна вещь, которую нужно принять во внимание - я не уверен, всегда ли можно безопасно использовать ObjectID для заказа последней версии. Использование временной метки может быть более верным подходом.

1 голос
/ 31 января 2012

Я печатал так же, как первый ответ Даймона, используя sort и limit.Это, вероятно, не рекомендуется, особенно с некоторыми драйверами (которые используют случайные числа вместо приращений для наименее значимой части) из-за способа генерации _id.Он имеет второе [в отличие от чего-то меньшего, например, миллисекунды], разрешение в качестве наиболее значимой части, но последнее число может быть случайным числом.Таким образом, если пользователь сохранял данные дважды в секунду (вероятно, маловероятно, но стоит отметить), вы можете получить немного вышедший из строя последний документ.

Подробнее см. http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification.по структуре ObjectID.

Я бы порекомендовал добавить явное поле versionNumber к вашим документам, чтобы вы могли делать запрос аналогичным образом, используя это поле, например:

db.coll.find({documentId: <id>}).sort({versionNum: -1}).limit(1);

изменить, чтобы ответить на вопрос в комментариях

Вы можете хранить обычный DateTime непосредственно в MongoDB, но он будет хранить точность только в миллисекундах в формате «DateTime» в MongoDB.Если это достаточно хорошо, это проще сделать.

BsonDocument doc = new BsonDocument("dt", DateTime.UtcNow);
coll.Insert (doc);
doc = coll.FindOne();
// see it doesn't have precision...
Console.WriteLine(doc.GetValue("dt").AsUniversalTime.Ticks);

Если вам нужна точность .NET DateTime (тики) / Timestamp, вы можете выполнить кучу приведений, чтобы она заработала, например:

BsonDocument doc = new BsonDocument("dt", new BsonTimestamp(DateTime.UtcNow.Ticks));
coll.Insert (doc);
doc = coll.FindOne();
// see it does have precision
Console.WriteLine(new DateTime(doc.GetValue("dt").AsBsonTimestamp.Value).Ticks);

обновите снова!

Похоже, реальное использование BsonTimestamp - генерировать уникальные временные метки с точностью до секунды.Таким образом, вы не должны злоупотреблять ими, как я делал в последних нескольких строках кода, и это, вероятно, испортит порядок результатов.Если вам нужно хранить DateTime с разрешением Tick (100 наносекунд), вам, вероятно, следует просто сохранить 64-битные int-тики, которые будут сортироваться в mongodb, а затем обернуть их в DateTime после того, как вы вытащитеопять база данных, вот так:

BsonDocument doc = new BsonDocument("dt", DateTime.UtcNow.Ticks);
coll.Insert (doc);
doc = coll.FindOne();
DateTime dt = new DateTime(doc.GetValue("dt").AsInt64);
// see it does have precision  
Console.WriteLine(dt.Ticks);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...