использует для времени создания mongodb ObjectId - PullRequest
49 голосов
/ 26 февраля 2011

ObjectId, используемый в качестве ключа по умолчанию в документах mongodb, имеет встроенную метку времени (вызов objectid.generation_time возвращает объект datetime). Таким образом, можно использовать это время генерации вместо сохранения отдельной метки времени создания? Как вы сможете эффективно сортировать по времени создания или запрашивать последние N элементов, используя эту встроенную метку времени?

Ответы [ 6 ]

73 голосов
/ 26 февраля 2011

Полагаю, поскольку MongoDB ObjectId содержит временную метку, вы можете отсортировать по «дате создания», если будете сортировать по objectId:

items.find.sort( [['_id', -1]] ) // get all items desc by created date.

А если вам нужны последние 30 созданных элементов, вы можете использовать следующий запрос:

items.find.sort( [['_id', -1]] ).limit(30) // get last 30 createad items 

Я на самом деле не уверен, я просто предполагаю, что упорядочение по _id должно работать, как описано выше. Я создам несколько тестов позже.

Обновление:

Да, это так. Если вы заказываете по _id, вы автоматически заказываете по _id дате создания. Я сделал небольшой тест в C #, м.б. кто-то заинтересован в этом:

  public class Item
  {
    [BsonId]
    public ObjectId Id { get; set; }

    public DateTime CreatedDate { get; set; }

    public int Index { get; set; }
  }



 [TestMethod]
 public void IdSortingTest()
 {
   var server = MongoServer.Create("mongodb://localhost:27020");
   var database = server.GetDatabase("tesdb");

   var collection = database.GetCollection("idSortTest");
   collection.RemoveAll();

   for (int i = 0; i <= 500; i++)
   {
     collection.Insert(new Item() { 
             Id = ObjectId.GenerateNewId(), 
             CreatedDate = DateTime.Now, 
             Index = i });
   }

   var cursor = collection.FindAllAs<Item>();
   cursor.SetSortOrder(SortBy.Descending("_id"));
   var itemsOrderedById = cursor.ToList();

   var cursor2 = collection.FindAllAs<Item>();
   cursor2.SetSortOrder(SortBy.Descending("CreatedDate"));
   var itemsOrderedCreatedDate = cursor.ToList();

   for (int i = 0; i <= 500; i++)
   {
     Assert.AreEqual(itemsOrderedById[i].Index, itemsOrderedCreatedDate[i].Index);
   }
}
17 голосов
/ 02 марта 2011

Да, вы можете использовать generation_time BSON ObjectId для ваших целей. Таким образом,

db.collection.find().sort({ _id : -1 }).limit(10)

вернет последние 10 созданных предметов. Однако, поскольку встроенные временные метки имеют точность в одну секунду, несколько элементов в любую секунду сохраняются в порядке их создания.

3 голосов
/ 26 октября 2011

Код для преобразования DateTime в соответствующую метку времени с драйвером c # выглядит следующим образом:

    public static ObjectId ToObjectId(this DateTime dateTime)
    {
        var timestamp = (int)(dateTime - BsonConstants.UnixEpoch).TotalSeconds;
        return new ObjectId(timestamp, 0, 0, 0);
    }

Более подробная информация здесь: http://www.danharman.net/2011/10/26/mongodb-ninjitsu-using-objectid-as-a-timestamp/

2 голосов
/ 06 апреля 2013

От: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-DocumentTimestamps

"сортировка по полю _id, в котором хранятся значения ObjectId, примерно эквивалентна сортировке по времени создания, хотя это соотношение не является строгим со значениями ObjectId, сгенерированными в нескольких системах в течение одной секунды."

1 голос
/ 19 января 2017

Для запроса проектов, созданных в течение 7 дней, я использую следующий фрагмент:

db.getCollection('projects').find({
  $where: function() {
    // last 7 days
    return Date.now() - this._id.getTimestamp() < (7 * 24 * 60 * 60 * 1000)
  }
}).sort({
  '_id': -1
})

, и если вы хотите получить элементы с указанными полями:

db.getCollection('projects').find({
  $where: function() {
    // last 7 days
    return Date.now() - this._id.getTimestamp() < (7 * 24 * 60 * 60 * 1000)
  }
}).sort({
  '_id': -1
}).toArray().map(function(item) {
  var res = {};
  res['Project Name'] = item.config.label;
  res['Author'] = item.author;
  res['Created At'] = item._id.getTimestamp().toLocaleDateString();
  res['Last Modified Date'] = item.config.lastModifDate.toLocaleString();
  return res;
});

, он вернет что-то вродеэто:

[{
  "Project Name": "Newsletter",
  "Author": "larry.chen",
  "Created At": "Thursday, January 19, 2017",
  "Last Modified Date": "Thursday, January 19, 2017 17:05:40"
}...]

PS: программное обеспечение, которое я использую для подключения к MongoDB: Robo 3T

Надеюсь, этопоможет вам.

1 голос
/ 26 февраля 2011

См.

http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-DocumentTimestamps

Возможно, однако, я бы предпочел иметь выделенную временную метку, а не полагаться на некоторые такие внутренние элементы, как временная метка, каким-то образом встроенная в некоторый идентификатор объекта.

...