【问题标题】:Basic between dates queries $gte, $lte, etc基本日期查询 $gte、$lte 等
【发布时间】:2021-05-01 21:18:25
【问题描述】:

我的 mongo 查询的正确时间格式存在问题。

我的问题是:

  • time.Time 是 mongo ISODate 对象的正确 go 类型吗?
  • 为什么我的时间解析似乎解析了一个完全不同的日期?

这里有一个完整的例子来说明我正在做的事情。

package main

import (
    // "fmt"
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

// Here's a JSON of the record as it is in the db
// { 
//  "_id" : ObjectId("5fa467af036d5f46914c423c"), 
//  "subscriptionRuleId" : "email@email", 
//  "eventDateTime" : ISODate("2020-11-05T20:59:27.096+0000"), 
//  "eventType" : "string-with-event-type", 
//  "passportAtlas" : "a long string", 
//  "_class" : "com.proj.info.model.dto.EventLog"
// }

type eventLog struct {
    SubscriptionRuleID string `json:"subscriptionRuleId,omitempty" bson:"subscriptionRuleId"`
    EventType string `json:"eventType" bson:"eventType"`
    EventDateTime time.Time `json:"eventDateTime" bson:"eventDateTime"`
    PassportAtlas string `json:"passportAtlas" bson:"passportAtlas`
}

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.Connect(ctx, clientOptions)

    if err != nil { log.Fatal(err) }

    err = client.Ping(ctx, nil)

    if err != nil { log.Fatal(err) }

    collection := client.Database("compose").Collection("eventLog")

    df := "2006-02-04"
    dateFrom, _ := time.Parse(df, "2020-11-20")
    dateTo, _ := time.Parse(df, "2020-11-21")

    // This does not seem to work. 
    // A log of the dates gives me the wrong dates

    log.Printf("\nFROM: %v\nTO: %v", dateFrom, dateTo)
    // OUTPUTS:
    // FROM: 2020-01-09 00:20:00 +0000 UTC
    // TO: 2020-01-10 00:21:00 +0000 UTC

    // Notice the dates are formatted wrong in the log.
    // Even though the dates are wrong, I would still match
    // Records with those wrong dates as i've got tens of thousands
    // over the last few years...
 
    query := bson.M{
        "eventDateTime": bson.M{
            "$gte": dateFrom,
            "$lt": dateTo,
        },
    }

    cur, err := collection.Find(ctx, query)

    if err != nil { log.Fatal(err) }

    defer cur.Close(context.Background())

    var eventLogs []eventLog

    for cur.Next(ctx) {
        var eventLog eventLog
        cur.Decode(&eventLog)
        eventLogs = append(eventLogs, eventLog)
    }

    if err := cur.Err(); err != nil { log.Fatal(err) }

    log.Printf("num records: %v", len(eventLogs))
}

【问题讨论】:

    标签: mongodb go bson


    【解决方案1】:

    BSON 只是二进制 JSON。 MongoDB 查询是使用类似结构构造的 BSON 文档,通过使用 bson.M(这是一个 map[string]interface{})作为对象和数组的值切片。还有一个bson.D 类型可用于构造保持其字段顺序的对象。

    bson 包的 API 文档解释了您应该知道的大部分内容。最重要的是 Go 类型以您期望的方式映射到它们的 bson 等价物。 Bson 日期映射到 time.Time。

    使用您的示例:

    query:=bson.M{"eventDateTime":bson.M{"$gte": fromDate, "$lt":toDate}}
    

    其中fromDatetoDatetime.Time 值。

    另一个例子,$in 查询可以写成:

    query:=bson.M{"field":bson.M{"$in":[]string{"value1","value2"}}}
    

    【讨论】:

    • 谢谢!我不知道为什么昨天没有点击我。我现在了解bson的情况。我已更新我的问题以反映您的正确查询并提供更多信息......现在我的问题是它似乎没有将我的日期格式化为正确的日期?
    • 使用 time.Time 值,不要将它们转换为字符串。 Mongodb 不会将日期存储为字符串,但是当您格式化日期时,它会将 db 中的日期值与字符串值进行比较,这将不匹配。只需使用 time.Time。
    【解决方案2】:

    这是一个示例,展示了我们如何使用日期范围在 MongoDB 中使用 $gte$lte 搜索文档

    在这里,我们将 CourseSearch 作为参数传递,该参数将从前端/UI 填充。

    后端服务将搜索Course集合中的数据。

    type CourseSearch struct {
        Subject     string          `json:"subject,omitempty" bson:"subject,omitempty"`
        System      string          `json:"system,omitempty" bson:"system,omitempty"`
        FromDate    time.Time       `json:"from_date,omitempty" bson:"from_date"`
        ToDate      time.Time       `json:"to_date,omitempty" bson:"to_date"`
    }
    
    func SearchByDate(ctx context.Context, searchCriteria *CourseSearch) {
    
        fromDate := searchCriteria.FromDate
        toDate := searchCriteria.ToDate
    
        database := db.Conn.Database("Education")
        metadataCollection := database.Collection("Course")
        cursor, err := metadataCollection.Find(
            ctx,
            bson.D{
                {"subject", searchCriteria.Subject},
                {"system", searchCriteria.System},
                {"duration", bson.D{{"$gte", fromDate}, {"$lt", toDate}} },
            })
    

    【讨论】:

      猜你喜欢
      • 2016-11-17
      • 2013-06-07
      • 2011-07-11
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      • 2021-09-17
      • 2022-12-05
      • 2016-12-23
      相关资源
      最近更新 更多