mongodbgographql-go

$push string as an array in mongo document


I'm having trouble understanding arrays in Go, especially with both graphql and mongo. With JS this all would've been a breeze for me, but I'm wondering if you can look at what I have and point out the obvious!

I'm looking for an object to be shaped like the following:

time
├── login
│   ├── 0
│   │   └── "2021-08-16T20:11:54-07:00"
│   ├── 1
│   │   └── "2021-08-16T20:11:54-07:00"
│   └── 2
        └── "2021-08-16T20:11:54-07:00"

models.go:

type Time struct {
    Login []string
}

type User struct {
    ID       graphql.ID
    Time     Time
}

schema.graphql:

type Time {
  login: [String!]!
}

type User {
  id:      ID!
  time:    Time!
}

database.go:

filter := bson.D{{Key: "email", Value: email}}
arr := [1]string{time.Now().Format(time.RFC3339)}
update := bson.D{
  {Key: "$push", Value: bson.D{
    {Key: "time.login", Value: arr},
  }},
}
result, err := collection.UpdateOne(ctx, filter, update)

I've also tried:

update := bson.D{
  {Key: "$push", Value: bson.D{
    {Key: "time.login", Value: time.Now().Format(time.RFC3339)},
  }},
}
result, err := collection.UpdateOne(ctx, filter, update)

But always end up with the same error:

error="write exception: write errors: [The field 'time.login' must be an array but is of type null in document {_id: ObjectId('611b28fabffe7f3694bc86dc')}]"


Solution

  • [1]string{} is an array. []string{} is a slice. The two are different. An array is a fixed size object. A slice can grow/shrink dynamically.

    In this case, you should not be using either, because $push gets a value, not a slice:

    update := bson.D{
      {Key: "$push", Value: bson.D{
        {Key: "time.login", Value: time.Now().Format(time.RFC3339)},
      }},
    }