MongoDB दो तिथियों के बीच की वस्तुओं का पता लगाएं


406

मैं मेनगोडब के अंदर स्टोरिंग ट्वीट्स के आसपास खेल रहा हूं, प्रत्येक ऑब्जेक्ट इस तरह दिखता है:

{
"_id" : ObjectId("4c02c58de500fe1be1000005"),
"contributors" : null,
"text" : "Hello world",
"user" : {
    "following" : null,
    "followers_count" : 5,
    "utc_offset" : null,
    "location" : "",
    "profile_text_color" : "000000",
    "friends_count" : 11,
    "profile_link_color" : "0000ff",
    "verified" : false,
    "protected" : false,
    "url" : null,
    "contributors_enabled" : false,
    "created_at" : "Sun May 30 18:47:06 +0000 2010",
    "geo_enabled" : false,
    "profile_sidebar_border_color" : "87bc44",
    "statuses_count" : 13,
    "favourites_count" : 0,
    "description" : "",
    "notifications" : null,
    "profile_background_tile" : false,
    "lang" : "en",
    "id" : 149978111,
    "time_zone" : null,
    "profile_sidebar_fill_color" : "e0ff92"
},
"geo" : null,
"coordinates" : null,
"in_reply_to_user_id" : 149183152,
"place" : null,
"created_at" : "Sun May 30 20:07:35 +0000 2010",
"source" : "web",
"in_reply_to_status_id" : {
    "floatApprox" : 15061797850
},
"truncated" : false,
"favorited" : false,
"id" : {
    "floatApprox" : 15061838001
}

मैं एक क्वेरी कैसे लिखूंगा जो create_at की जांच करता है और 18:47 और 19:00 के बीच सभी वस्तुओं को पाता है? क्या मुझे अपने दस्तावेज़ों को अपडेट करने की आवश्यकता है ताकि तिथियां एक विशिष्ट प्रारूप में संग्रहीत हों?


आप यह नहीं कहते कि आप किस क्षेत्र में क्वेरी चाहते हैं?
शिंगारा

ओह, मैं create_at को क्वेरी करना चाहता हूं और सभी को दो तिथियों के बीच ढूंढना चाहता हूं।
टॉम

मैं उत्सुक हूं कि डेट ओबज का उपयोग करके टाइमस्टैम्प का उपयोग क्यों नहीं किया जाता है?
सिंह

4
@ लियो युग या जो कुछ भी मानव पठनीयता है, के बाद मिलीसेकंड पर दिनांक ऑब्जेक्ट के साथ सबसे बड़ा लाभ है। इस मामले में, अपनी शुरुआत सीमा निर्धारित 2010-04-29T00:00:00.000Zकरना एक ही तिथि / समय को मिलीसेकंड में गणना करने की तुलना में बहुत आसान है। तुम भी समय क्षेत्र रूपांतरण बहुत आसानी से कर सकते हैं। इसके अलावा, तिथियां पहले से ही लीप डेज, लीप सेकंड और अन्य विषमताओं जैसी चीजों को संभालती हैं जिन्हें आप आमतौर पर खुद को संभालना नहीं चाहते हैं।
१22:

जवाबों:


619

एक तिथि सीमा (विशिष्ट महीने या दिन) के लिए क्वेरी में MongoDB कुकबुक इस मामले पर एक बहुत अच्छा विवरण है, लेकिन नीचे कुछ मैं अपने आप को बाहर करने की कोशिश की है और यह काम करने लगता है।

items.save({
    name: "example",
    created_at: ISODate("2010-04-30T00:00:00.000Z")
})
items.find({
    created_at: {
        $gte: ISODate("2010-04-29T00:00:00.000Z"),
        $lt: ISODate("2010-05-01T00:00:00.000Z")
    }
})
=> { "_id" : ObjectId("4c0791e2b9ec877893f3363b"), "name" : "example", "created_at" : "Sun May 30 2010 00:00:00 GMT+0300 (EEST)" }

मेरे प्रयोगों के आधार पर आपको अपनी तिथियों को एक प्रारूप में क्रमबद्ध करने की आवश्यकता होगी जो MongoDB का समर्थन करता है, क्योंकि निम्नलिखित ने अवांछित खोज परिणाम दिए हैं।

items.save({
    name: "example",
    created_at: "Sun May 30 18.49:00 +0000 2010"
})
items.find({
    created_at: {
        $gte:"Mon May 30 18:47:00 +0000 2015",
        $lt: "Sun May 30 20:40:36 +0000 2010"
    }
})
=> { "_id" : ObjectId("4c079123b9ec877893f33638"), "name" : "example", "created_at" : "Sun May 30 18.49:00 +0000 2010" }

दूसरे उदाहरण में कोई परिणाम की उम्मीद नहीं की गई थी, लेकिन अभी भी एक मिल गया था। ऐसा इसलिए है क्योंकि एक मूल स्ट्रिंग तुलना की जाती है।


3
दिलचस्प लगता है, लेकिन क्या संग्रहीत तारीख को एक विशिष्ट प्रारूप में होना चाहिए। मैं सिर्फ यह बता रहा हूं कि ट्विटर द्वारा क्या प्रदान किया गया था, क्या इसे अलग प्रारूप में बदलने की आवश्यकता है?
टॉम

7
आपने शायद टाइमस्टैम्प को तार के रूप में संग्रहीत किया है, इसलिए मुझे लगता है कि MongoDB को एहसास नहीं होगा कि वे वास्तव में तारीखों में हैं। इस प्रकार उन पर एक श्रेणी क्वेरी करने से एक वर्णमाला रेंज क्वेरी (उदाहरण के लिए "जन सोम 01.01.2010" "जन सन 01.01.1000" से पहले होगी)। यह संभवत: सभी तिथि डेटा को मोंगोडीबी प्रारूप में प्रारूपित करने के लिए समझ में आएगा, जो मुझे लगता है कि सिर्फ सादे जावास्क्रिप्ट तिथि है।
पोनज़ाओ

2
मैंने इसका उपयोग अपने तार को तारीख वस्तुओं में बदलने के लिए किया है। stackoverflow.com/questions/2900674/…
टॉम

ठीक है! मुझे लगता है कि रसोई की किताब में बताई गई रेंज क्वेरीज़ को तब काम करना चाहिए, क्या आपने उन्हें पहले ही आज़मा लिया था?
पोनज़ाओ

हाँ, एक बार जब मैं उम्मीद के मुताबिक काम कर रही रसोई की किताबों के उदाहरणों को सही कर रहा था।
टॉम

35

स्पष्ट करना। यह जानना महत्वपूर्ण है कि:

  • हां, आपको एक जावास्क्रिप्ट दिनांक ऑब्जेक्ट पास करना होगा।
  • हां, इसे ISODate फ्रेंडली होना होगा
  • हां, मेरे अनुभव से यह काम करने के लिए, आपको आईएसओ को तारीख में हेरफेर करने की आवश्यकता है
  • हां, तिथियों के साथ काम करना आम तौर पर एक थकाऊ प्रक्रिया है, और मोंगो कोई अपवाद नहीं है

यहां कोड का एक कार्यशील स्निपेट है, जहां हम मानगो को सुनिश्चित करने के लिए थोड़ी सी तारीख में हेरफेर करते हैं (यहां मैं मानगो मॉड्यूल का उपयोग कर रहा हूं और उन पंक्तियों के लिए परिणाम चाहता हूं, जिनकी तिथि विशेषता से पहले की तारीख से कम है) यह सही है:

var inputDate = new Date(myDate.toISOString());
MyModel.find({
    'date': { $lte: inputDate }
})

1
स्पष्टता के लिए एक प्लस। यदि आपका बैकएंड में उपयोग करने का क्षण है, तो यह अभी भी toISOString () फ़ंक्शन को बरकरार रखता है। मैं अपने प्रश्नों के लिए समय जोड़ने और घटाने के लिए क्षण का उपयोग करता हूं।
वोकजैक्स

17

MongoDB वास्तव में एक तिथि के मिल को इंट (64) के रूप में संग्रहीत करता है, जैसा कि http://bsonspec.org/#/spspification द्वारा निर्धारित है

हालाँकि, यह बहुत भ्रमित कर सकता है जब आप तारीखों को पुनः प्राप्त करते हैं क्योंकि क्लाइंट ड्राइवर अपने स्वयं के स्थानीय समयक्षेत्र के साथ एक दिनांक ऑब्जेक्ट को तुरंत हटा देगा। मोंगो कंसोल में जावास्क्रिप्ट ड्राइवर निश्चित रूप से ऐसा करेगा।

इसलिए, यदि आप अपने टाइमज़ोन की परवाह करते हैं, तो सुनिश्चित करें कि आप जानते हैं कि जब आप इसे वापस लेते हैं तो यह क्या होना चाहिए। यह प्रश्नों के लिए इतना महत्वपूर्ण नहीं होना चाहिए, क्योंकि यह अभी भी उसी इंट (64) के बराबर होगा, भले ही आपकी तिथि ऑब्जेक्ट (मुझे आशा है) किस समय के लिए है। लेकिन मैं निश्चित रूप से वास्तविक तारीख वस्तुओं (तार नहीं) के साथ प्रश्न करता हूं और चालक को अपनी बात करने देता हूं।


16

अजगर और pymongo

pymongoसंग्रह posts( ट्यूटोरियल पर आधारित ) के साथ पायथन में दो तिथियों के बीच वस्तुओं को खोजना :

from_date = datetime.datetime(2010, 12, 31, 12, 30, 30, 125000)
to_date = datetime.datetime(2011, 12, 31, 12, 30, 30, 125000)

for post in posts.find({"date": {"$gte": from_date, "$lt": to_date}}):
    print(post)

जहां प्रकार के {"$gte": from_date, "$lt": to_date}संदर्भ में सीमा निर्दिष्ट करता है datetime.datetime


ये काम नहीं कर रहा है। जब भी मैं इस क्वेरी को चलाता हूं मुझे डिफ़ॉल्ट रूप से पूर्ण प्रतिक्रिया मिलती है और फ़िल्टर की गई प्रतिक्रिया नहीं होती है
अभय

14
db.collection.find({"createdDate":{$gte:new ISODate("2017-04-14T23:59:59Z"),$lte:new ISODate("2017-04-15T23:59:59Z")}}).count();

उस collectionसंग्रह के नाम से प्रतिस्थापित करें जिसे आप क्वेरी निष्पादित करना चाहते हैं


3
यह स्वीकृत उत्तर (7 साल पहले प्रदान किया गया) को क्या जोड़ता है?
डैन डस्केलस्क्यू

1
@DanDascalescu -may यह कुछ भी नहीं जोड़ा गया लेकिन यहां आपकी चिंता क्या है?
GSK

17
डुप्लिकेट उत्तर लोगों के समय को बर्बाद करते हैं।
दान डैस्कलेस्क्यू

10

इस कोड का उपयोग करके दो तिथियों के बीच के रिकॉर्ड को खोजने के लिए उपयोग करें $gteऔर $lt:

db.CollectionName.find({"whenCreated": {
    '$gte': ISODate("2018-03-06T13:10:40.294Z"),
    '$lt': ISODate("2018-05-06T13:10:40.294Z")
}});

8 साल पहले प्रदान किए गए स्वीकृत उत्तर में यह क्या जोड़ता है?
डैन डस्केलस्क्यू

7

Moment.js और तुलना क्वेरी ऑपरेटर के साथ प्रयोग करना

  var today = moment().startOf('day');
  // "2018-12-05T00:00:00.00
  var tomorrow = moment(today).endOf('day');
  // ("2018-12-05T23:59:59.999

  Example.find(
  {
    // find in today
    created: { '$gte': today, '$lte': tomorrow }
    // Or greater than 5 days
    // created: { $lt: moment().add(-5, 'days') },
  }), function (err, docs) { ... });

2

अपनी तिथियों को GMT टाइमज़ोन में बदलें क्योंकि आप उन्हें मानगो में भर रहे हैं। इस तरह वहाँ एक समय क्षेत्र मुद्दा कभी नहीं है। जब आप प्रस्तुति के लिए डेटा वापस खींचते हैं तो बस ट्विटर / टाइमज़ोन फ़ील्ड पर गणित करें।


2

YYYYMMDDHHMMSS फॉर्म के पूर्णांक को स्ट्रिंग में क्यों न बदलें? समय की प्रत्येक वृद्धि तब एक बड़ा पूर्णांक बनाएगी, और आप आईएसओ समय को बदलने के बारे में चिंता करने के बजाय पूर्णांक पर फ़िल्टर कर सकते हैं।


क्योंकि समय अभी मेरे स्थानीय समयक्षेत्र में नहीं हो रहा है।
माइकल कोल

2
यह एक बुरा सपना बन जाता है जब आप हर जगह और उस प्रारूप से समय को बदलना शुरू करते हैं। यदि आप कुछ ऐसा करने जा रहे हैं, तो JS दिनांक ऑब्जेक्ट से .getTime () से वापसी मान का बहुत कम से कम उपयोग करें।
नीक वोंग

1
यही कारण है कि हम हमेशा UTC में डेटा स्टोर करते हैं
कोडवर्ड

2

मूंगोडब में डेट डेटा के बीच खोजने के लिए $ gte और $ lte का उपयोग करें

var tomorrowDate = moment(new Date()).add(1, 'days').format("YYYY-MM-DD");
db.collection.find({"plannedDeliveryDate":{ $gte: new Date(tomorrowDate +"T00:00:00.000Z"),$lte: new Date(tomorrowDate + "T23:59:59.999Z")}})

1
आपके उत्तर में थोड़ा टाइपो $ $ नहीं मिलता है :)
बॉब

1
क्षमा करें, मैंने बहुत थका देने वाली स्थिति का उत्तर दिया, इसलिए मैंने गलती की। मेरे उत्तर को अपडेट करने के लिए आपकी मदद के लिए धन्यवाद। आपने अच्छा काम किया :) @bus
KARTHIKEYAN.A

2

आप इसे भी देख सकते हैं। यदि आप इस विधि का उपयोग कर रहे हैं, तो मानस डेटाबेस से मान प्राप्त करने के लिए पार्स फ़ंक्शन का उपयोग करें:

db.getCollection('user').find({
    createdOn: {
        $gt: ISODate("2020-01-01T00:00:00.000Z"),
        $lt: ISODate("2020-03-01T00:00:00.000Z")
    }
})

1
mongoose.model('ModelName').aggregate([
    {
        $match: {
            userId: mongoose.Types.ObjectId(userId)
        }
    },
    {
        $project: {
            dataList: {
              $filter: {
                 input: "$dataList",
                 as: "item",
                 cond: { 
                    $and: [
                        {
                            $gte: [ "$$item.dateTime", new Date(`2017-01-01T00:00:00.000Z`) ]
                        },
                        {
                            $lte: [ "$$item.dateTime", new Date(`2019-12-01T00:00:00.000Z`) ]
                        },
                    ]
                 }
              }
           }
        }
     }
])

1

आप कुल मिलाकर उपयोग करने के बजाय इसे देख सकते हैं या प्रयास कर सकते हैं

db.getCollection('user').find({
    createdOn: {
        $gt: ISODate("2020-01-01T00:00:00.000Z"),
        $lt: ISODate("2020-03-01T00:00:00.000Z")
    }
})

0

मैंने अपनी आवश्यकताओं के अनुसार इस मॉडल में कोशिश की, मुझे एक तारीख को संग्रहीत करने की आवश्यकता है जब कभी कोई वस्तु बनाई जाती है बाद में मैं अपनी HTML फ़ाइल में दो तिथियों के बीच सभी रिकॉर्ड (दस्तावेज) प्राप्त करना चाहता हूं मैं निम्नलिखित प्रारूप mm / dd / yyyy का उपयोग कर रहा था

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>

    <script>
//jquery
    $(document).ready(function(){  
    $("#select_date").click(function() { 
    $.ajax({
    type: "post",
    url: "xxx", 
    datatype: "html",
    data: $("#period").serialize(),  
    success: function(data){
    alert(data);
    } ,//success

    }); //event triggered

    });//ajax
    });//jquery  
    </script>

    <title></title>
</head>

<body>
    <form id="period" name='period'>
        from <input id="selecteddate" name="selecteddate1" type="text"> to 
        <input id="select_date" type="button" value="selected">
    </form>
</body>
</html>

मेरे py (python) फ़ाइल में मैंने इसे निम्नलिखित तरीके से "iso fomate" में बदल दिया

date_str1   = request.POST["SelectedDate1"] 
SelectedDate1   = datetime.datetime.strptime(date_str1, '%m/%d/%Y').isoformat()

और मेरे संग्रह में फ़ील्ड के रूप में "चयनित" के साथ मेरे dbmongo संग्रह में सहेजा गया

क्वेरी के बाद उपयोग की गई 2 तिथियों के बीच डेटा या दस्तावेजों को प्राप्त करने के लिए

db.collection.find( "SelectedDate": {'$gte': SelectedDate1,'$lt': SelectedDate2}})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.