web-dev-qa-db-ja.com

mongodb ObjectId作成時に使用します

Mongodbドキュメントでデフォルトキーとして使用されるObjectIdにはタイムスタンプが埋め込まれています(objectid.generation_timeを呼び出すとdatetimeオブジェクトが返されます)。では、別の作成タイムスタンプを保持する代わりに、この生成時間を使用することは可能ですか?この埋め込みタイムスタンプを使用して、作成時間で並べ替えたり、最後のN個のアイテムを効率的に照会したりするにはどうすればよいですか?

49
kefeizhou

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#で小さなテストをしました、mb誰かがそれに興味を持っています:

  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);
   }
}
73
Andrew Orsich

はい、BSON ObjectIdのgeneration_timeを目的に使用できます。そう、

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

最後に作成された10個のアイテムを返します。ただし、埋め込まれたタイムスタンプの精度は1秒なので、1秒以内の複数のアイテムは作成順に保存されます。

17
user105991

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/

3
DanH

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

「ObjectId値を格納する_idフィールドでの並べ替えは、作成時間による並べ替えとほぼ同等ですが、この関係は、1秒以内に複数のシステムで生成されたObjectId値に厳密ではありません。」

2
wprl

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
Chen Dachao

見る

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

おそらく実行可能ですが、何らかの方法で何らかのオブジェクトIDに埋め込まれたタイムスタンプのような内部に依存するのではなく、常に専用のタイムスタンプを持つことを好むでしょう。

1
Andreas Jung