2017-07-14 4 views
0

私は$ currentDateを使用して挿入する日付を含むフィールドを持つmongoドキュメントを持っていますので、ドキュメントを挿入するとmongoサーバーの日付が入ります。 日付フィールドとサーバー日付の差が10分以上あることをすべてのドキュメントに照会してフィルタリングしたいとします。MongoDB queryサーバー時刻の日付フィールド

はこのDBを想定します。

{ "_id" : 1, "item" : "abc", "price" : 10, "fee" : 2, "discount" : 5, "date" : ISODate("2017-07-14T08:00:00Z") } 
{ "_id" : 2, "item" : "jkl", "price" : 20, "fee" : 1, "discount" : 2, "date" : ISODate("2017-07-14T08:05:00Z") } 

は、私が上でクエリを実行すると仮定し、「2017-07-14T08:10:01Z」サーバの日付、 私は、クエリだけで最初の項目を返すことをしたいです。

db.items.aggregate([ 
{$project : {lut : {$subtract: ["** server date **", "$date" ]}}}, 
{$match : { lut : {$gte : 10*60*1000 }}} ]); 

クエリを実行しているときにサーバーの日付を取得するにはどうすればよいですか。 私はnodeJSサーバからクエリを実行しています。サーバの日付をnew Date()に置き換えると、mongoサーバではなくノードサーバの日付が取得されます。

答えて

0

のMongoDBサーバーは、$ CURRENTDATE演算子を使用して更新フィールドへと許すが、私は、クエリフィルタのように日付を使用するための任意のオプションを見つけることができませんでした。

ただし、「サーバー上でJavaScript関数を保存する」https://docs.mongodb.com/manual/tutorial/store-javascript-function-on-server/ を使用し、日付を返す関数を追加するオプションがあります。

+0

回答を書く代わりにより多くの情報がある場合は、質問を更新できます。こうすることで、人々はあなたの質問に答える前に情報を見つけることができます。 – bogdanciobanu

2

これは、最初の一見よりも難解です。レプリケーションとシャーディングが関係する場合、すべてのMongoインスタンスのクロック間の完全な同期を保証することは困難です。これは開発チームが説明した$ currentDateがクエリ用に拡張されなかった理由です。

つまり、完璧な解決策は存在しませんが、回避策について考えることができます。 serverStatus関数は、サーバ時間を含むMongoクラスタに関する情報を返します。クライアントコードを初期化しているときにこの関数を呼び出し、クライアントの時刻とサーバーの時刻の差を見つけることができます。この違いがあると、その差で訂正されたクライアント時間に基づいて照会を行うことができます。ここでは、Pythonの抜粋です:

import datetime 
import pymongo 
client = pymongo.MongoClient() 
db = client.test_Db 
server_time = db.command("serverStatus")['localTime'] 
local_time = datetime.datetime.now() 
difference = server_time - local_time 


db.test_collection.find({'date': {'$lt': datetime.datetime.now() - datetime.timedelta(minutes=10) + difference}}) 

が、これは時間がサーバー上で測定された瞬間、それがクライアント上で測定された時間との間の誤差を持っていることに注意してください。このエラーは、情報がサーバーからクライアントに送信されている期間の影響を受けます。あなたのユースケースによっては、データベースから返された文書の数が増えたり少なくなったりする可能性があります。最初にクライアントとサーバの時刻を取得すると、10分+エラーより古い文書が届くので、いくつかの文書が欠落します。一方、サーバ上で時間を最初に取得してからクライアント上で10分より古いドキュメントを受信すると、エラーが表示されるので、いくつかの追加ドキュメントがあります。いずれかのケースが受け入れられるかどうかは、アップです。

もう1つのことは、1つの制限を設定すると、10分を超えて更新される文書がますます多くなるためです。また、同じ文書を何度も何度も受け取っています。あなたはまた、下限を置くことについて考えるべきです。

+0

ありがとうございます、チケットのように更新してください。これは回避策ですが、サーバーを2回呼び出して時計を同期し続ける必要があります。私は、テストとセットアトミックなシングルコールで最後の更新時間を設定します。 –