1

The trouble I've been having is that the code bellow only works if the token isn't in an array, (or is considered the original refresh token the rest descend from). I'm wasting so much precious energy trying to find a way to return the correct session.

// Find the current sessions info
currentSession := model.Session{}
lookupSession := bson.D{{Key: "token", Value: refreshToken}}
_ := tokensCol.FindOne(ctx, lookupSession).Decode(&currentSession)
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDcyMzAxNTJ9.R-Tm8sgs..."
userID: "1"
userAgent: ""
ip: ""
exp: 1647230152
valid: false
original: true
family:
   0:
      token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDcyMzAyNTJ9.noqkeUYW..."
      userID: "1"
      userAgent: ""
      ip: ""
      exp: 1647230252
      valid: true
      original: false

Is there a one stop shop for returning the object the token resides either at the top-level of the document or nested within the family array? The code bellow partially works, but returns the entire document starting with the original token. Not sure how to shape the data retrieved

currentSession := model.Session{}
filter := bson.M{
    "family": bson.M{
        "$elemMatch": bson.M{"token": refreshToken},
    },
}
_ = tokensCol.FindOne(ctx, filter).Decode(&currentSession)

fmt.Println(currentSession)

Returns:

{c8ncjdiaas68dh9fq1d0 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDcyMzcwNjJ9.KlR1mdC0UBnGfxr31MZwzoE7tTVQwuN5uciteSqh8Kg 1 1647237062 false true [{c8ncjhaaas68dh9fq1dg eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDcyMzcwNzd9.lx6MIBN_pzlKei9DWr0-k-kvr6yLJ4XfhGSTNNVqRKY 1 1647237077 true false []}]}

EDIT: Great, however.. I'm still only returning the original token at the top of the document and not the nested object that I need? The only difference is that the value of the token returns correctly when instead of throwing "token": 1, I say "token": refreshToken

session := model.Session{}
lookupSession := bson.M{
    "$or": []bson.M{
        {"token": refreshToken},
        {"family.token": refreshToken},
    },
}
opts := options.FindOne().SetProjection(
    bson.M{
        "token":     refreshToken,
        "userid":    1,
        "useragent": 1,
        "ip":        1,
        "exp":       1,
        "valid":     1,
        "original":  1,
    },
)
lookupErr := tokensCol.FindOne(ctx, lookupSession, opts).Decode(&session)

I really need the returned document from FindOne to include specific data from the object and not the top-level of the document. As I won't be running checks on that, as it would be invalid. Any Comments or advice for this??

  • 1
    If you need those fields, then why are not selecting them with the projection? `SetProjection(bson.M{"token": refreshToken})` this projection will only select the `token` field. If you need multiple fields, list all, or the easiest is to not specify a projection so you'll get the complete document. – icza Mar 16 '22 at 18:05
  • @icza Any thoughts on my current position? I would think that the projection is what I'd need in the case of trying to find the specific token when there are many objs in the array? – user16838682 Mar 16 '22 at 21:54
  • The projection has nothing to do with finding the right document. The projection is to omit some fields when retrieving the result. If you don't know what it is, don't use it (yet). Finding the right document is about the filter document `lookupSession`. – icza Mar 17 '22 at 07:23

1 Answers1

1

So basically you want to find a document that has a token field OR an element in the family array that has a token field with a given value? That's simply an $or condition, so use this lookupSession filter document:

lookupSession := bson.M{
    "$or": []bson.M{
        {"token": refreshToken},
        {"family.token": refreshToken},
    },
}

If you don't want to retrieve the complete result document, use projection. For an example, see How to filter fields from a mongo document with the official mongo-go-driver

icza
  • 389,944
  • 63
  • 907
  • 827