admin管理员组文章数量:1398756
I'm using the mongo-go-driver (/mongodb/mongo-go-driver/mongo) and I'm trying to do the equivalent of
db.getCollection('mycollection').aggregate([
{ $lookup: {
from: "anothercollection",
localField: "_id",
foreignField: "foreignID",
as: "matched_docs"
}},
{ $match: { "matched_docs": { $eq: [] } } },
{ $project: { "matched_docs": 0 } },
{ $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
])
I can't figure out how to put the Javascript mands in using this method.
pipeline := bson.NewArray(
bson.VC.DocumentFromElements(
bson.EC.SubDocumentFromElements(
//yada, yada, yada...
cursor, err := collection.Aggregate(ctx, pipeline)
(In general, I dislike this method, anyway. I want to be able to design queries in Robo 3T and copy them to my code just like I do with MySQL Workbench and PHP)
This method yields an empty *bson.Array in pipeline
pipelineJSON := `[
{ $lookup: {
from: "anothercollection",
localField: "_id",
foreignField: "interactionID",
as: "matched_docs"
}},
{ $match: { "matched_docs": { $eq: [] } } },
{ $project: { "matched_docs": 0 } },
{ $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
]`
pipeline, err = bson.ParseExtJSONArray(pipelineJSON)
I'd really love it if there were a way to send Mongo a mand as a string (like I was typing it into Robo 3T) and get a *mongo.Cursor back. Is there a better driver (that is still supported by someone) that I should use instead? Do I need to code my own?
Thanks!
I'm using the mongo-go-driver (https://godoc/github./mongodb/mongo-go-driver/mongo) and I'm trying to do the equivalent of
db.getCollection('mycollection').aggregate([
{ $lookup: {
from: "anothercollection",
localField: "_id",
foreignField: "foreignID",
as: "matched_docs"
}},
{ $match: { "matched_docs": { $eq: [] } } },
{ $project: { "matched_docs": 0 } },
{ $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
])
I can't figure out how to put the Javascript mands in using this method.
pipeline := bson.NewArray(
bson.VC.DocumentFromElements(
bson.EC.SubDocumentFromElements(
//yada, yada, yada...
cursor, err := collection.Aggregate(ctx, pipeline)
(In general, I dislike this method, anyway. I want to be able to design queries in Robo 3T and copy them to my code just like I do with MySQL Workbench and PHP)
This method yields an empty *bson.Array in pipeline
pipelineJSON := `[
{ $lookup: {
from: "anothercollection",
localField: "_id",
foreignField: "interactionID",
as: "matched_docs"
}},
{ $match: { "matched_docs": { $eq: [] } } },
{ $project: { "matched_docs": 0 } },
{ $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
]`
pipeline, err = bson.ParseExtJSONArray(pipelineJSON)
I'd really love it if there were a way to send Mongo a mand as a string (like I was typing it into Robo 3T) and get a *mongo.Cursor back. Is there a better driver (that is still supported by someone) that I should use instead? Do I need to code my own?
Thanks!
Share Improve this question edited Sep 9, 2018 at 9:51 Andrew Springman asked Sep 8, 2018 at 11:54 Andrew SpringmanAndrew Springman 631 silver badge10 bronze badges 5- You can't. You need to find an equivalent way of doing that in Go. That JS isn't anything special--it's just returning a date value a certain time in the past. Should be absolutely trivial to do the same without JS. – Jonathan Hall Commented Sep 8, 2018 at 12:49
- Flimzy: you are absolutely right that the JS isn't anything special and I can replace it with time.Now().AddDate(0, 0, -1).UTC().Format(time.RFC3339) in golang. To all: To clarify what I'm driving at, does anyone know where I can find documentation on the underlying mongodb api that the driver is using so I can determine if there is a javascript parser available at that level or only in the mongo shell? – Andrew Springman Commented Sep 9, 2018 at 2:33
- Also, to clarify, the JS wasn't the only thing that worked in Robo3T/Mongo shell and failed in ParseExtJSONArray. ParseExtJSONArray requires all the aggregation stages and functions be surrounded with quotes (instead of bare). Is there a way for a client golang program to query mongo like the shell? – Andrew Springman Commented Sep 9, 2018 at 2:39
- If your request is "Where do I find MongoDB docs?" the question is, unfortunately, off-topic here, as resource requests are off-topic. However, it should be easy to find MongoDB API docs. – Jonathan Hall Commented Sep 9, 2018 at 7:39
- Fair enough. I suppose that the on-topic elements of my question are now resolved and I'm pivoting into off-topic. I'll answer the question with what I've learned. – Andrew Springman Commented Sep 9, 2018 at 9:34
2 Answers
Reset to default 6I can't figure out how to put the Javascript mands in using this method.
Although I understand this is not the preferred method for your use case, this is how to construct the aggregation pipeline as bson.D using mongo-go-driver v1.0:
pipeline := mongo.Pipeline{
{{"$lookup", bson.D{
{"from", "tour"},
{"localField", "_id"},
{"foreignField", "foreignID"},
{"as", "matched_docs"},
}}},
{{"$match", bson.D{
{"matched_docs", bson.D{
{"$eq", bson.A{}}},
},
}}},
{{"$project", bson.D{
{"matched_docs", 0},
}}},
{{"$match", bson.D{
{"dateTimeGMT", bson.D{
{"$lt", time.Now().AddDate(0, 0, -1).UTC().Format(time.RFC3339)},
},
},
}}},
}
{ $project: { "matched_docs": 0 } },
You can also bined the two $match
into a single pipeline stage instead, and then attach $project
at the end. For example:
db.collection.aggregate([
{ "$lookup":{
"from":"anothercollection",
"localField":"_id",
"foreignField":"foreignID",
"as":"matched_docs"}
},
{ "$match": { "matched_docs": { "$eq": [] },
"datetimegmt": { "$lt": (new Date(Date.now()-1000*60*60*24)).toISOString() }
}
},
{ "$project": { "matched_docs": 0 } }
]);
{ $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
Based on the $match
value, it looks like you're storing date as string
instead of a Date object. I would suggest to store dates as the proper Date
objects for better index performance.
Using ParseExtJSONArray DOES work, but, unlike Mongo Shell, you cannot include JS or unquoted aggregation stages / expression operators
mongo shell provides some convienient methods/types i.e. ObjectID()
, etc to construct MongoDB Extended JSON. The mongo
shell is more than just a JavaScript shell.
If your aim just to evaluate a JavaScript expression, you can utilise a JavaScript interpreter for Go (otto). A rough example would be:
// Note the unquoted fields, as JSON is JavaScript native.
raw := `[
{ "$lookup": {
from: "anothercollection",
localField: "_id",
foreignField: "foreignID",
as: "matched_docs"
}},
{ $match: { "matched_docs": { $eq: [] },
"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString() },
}
},
{ $project: { "matched_docs": 0 } },
]`
vm := otto.New()
// Evaluate JS expression
jsvalue, err := vm.Eval(raw)
// Export to Go interface{}
output, err := jsvalue.Export()
// Convert interface{} to bson.Document bytes
bsonbytes, err := bson.Marshal(output)
// Convert bson.Document bytes to bson.Document
pipeline, err := bson.UnmarshalDocument(bsonbytes)
Note as mentioned above, there are some objects that will not be recognised by a normal JavaScript interpreter i.e. ObjectId()
I want to be able to design queries in Robo 3T and copy them to my code just like I do with MySQL Workbench and PHP
Although currently does not support Go, worth mentioning that MongoDB Compass has a feature to Export Query to Language. Current version (1.15) supports Java, Node, C# and Python3. Hopefully Go would be in the future.
Using ParseExtJSONArray DOES work, but, unlike Mongo Shell, you cannot include JS or unquoted aggregation stages / expression operators. Note that the ISO date for the parison is calculated in golang and the aggregation stages and aggregtion expression operators have been surrounded by quotes.
pipelineJSON := fmt.Sprintf(`[
{ "$lookup": {
"from": "another_collection",
"localField": "_id",
"foreignField": "interactionID",
"as": "matched_docs"
}},
{ "$match": { "matched_docs": { "$eq": [] } } },
{ "$project": { "matched_docs": 0 } },
{ "$match": {"dateTimeGMT":{"$lt": "%s"}} }
]`, time.Now().AddDate(0, 0, -1).UTC().Format(time.RFC3339))
pipeline, err = bson.ParseExtJSONArray(pipelineJSON)
With the driver I asked about, that's the answer.
本文标签: mongodbHow to run an aggregate query via mongogodriver that has javascript in itStack Overflow
版权声明:本文标题:mongodb - How to run an aggregate query via mongo_go_driver that has javascript in it? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744766420a2624069.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论