从Go Mongo API返回单个对象

huangapple go评论76阅读模式
英文:

Returning a single object from Go Mongo API

问题

我遇到的问题是,下面的代码只有在令牌不在数组中(或被视为原始刷新令牌,其余令牌从中派生)时才起作用。我浪费了很多宝贵的精力,试图找到一种返回正确会话的方法。

// 查找当前会话信息
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

是否有一种一站式方法,可以返回令牌所在的对象,无论是在文档的顶层还是嵌套在family数组中?下面的代码部分工作正常,但返回以原始令牌开头的整个文档。不确定如何整理检索到的数据。

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

fmt.Println(currentSession)

返回:

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

编辑:很好,但是...我仍然只返回文档顶部的原始令牌,而不是我需要的嵌套对象?唯一的区别是当我说"token": refreshToken而不是"token": 1时,令牌的值返回正确。

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)

我真的需要从FindOne返回的文档中包含对象的特定数据,而不是文档的顶层。因为我不会对其进行检查,因为它是无效的。对此有什么评论或建议吗?

英文:

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

得分: 1

所以基本上你想找到一个具有token字段的文档,或者在family数组中有一个具有给定值的token字段的元素?这只是一个$or条件,所以使用以下lookupSession过滤文档:

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

如果你不想检索完整的结果文档,可以使用投影。有一个示例,请参考https://stackoverflow.com/questions/53120116/how-to-filter-fields-from-a-mongo-document-with-the-official-mongo-go-driver/53155795#53155795

英文:

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 https://stackoverflow.com/questions/53120116/how-to-filter-fields-from-a-mongo-document-with-the-official-mongo-go-driver/53155795#53155795

huangapple
  • 本文由 发表于 2022年3月14日 11:22:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/71462673.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定