[GODRIVER-771] Find with $in Created: 17/Jan/19  Updated: 27/Oct/23  Resolved: 05/Feb/19

Status: Closed
Project: Go Driver
Component/s: CRUD
Affects Version/s: 0.2.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: John Daniels Assignee: Isabella Siu (Inactive)
Resolution: Works as Designed Votes: 0
Labels: Bug
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Ubuntu 18.04, Mongo version 4.0, GO version 1.11



 Description   

When searching for objects using $in, the cursor always drops the first found object. All subsequent displays are normal.

ids := []string{"1","2","3"}
filter := bson.M{"terminal_id": bson.M{"$in": ids}}
cursor, err := s.db.Collection(collectionTerminal).Find(ctx, filter)
if err != nil {
   return nil, err
}
defer cursor.Close(ctx)
 
var terminalList []*terminal.Terminal
for cursor.Next(ctx) {
   var term *terminal.Terminal
   err := cursor.Decode(&term)
   if err != nil {
      fmt.Println(err)
      return nil, err
   }
   terminalList = append(terminalList, term)
}
// in terminalList: [{"id":"2"}, {"id":"3"}]
// must be: [{"id":"1"}, {"id":"2"}, {"id":"3"}]

 

 



 Comments   
Comment by John Daniels [ 05/Feb/19 ]

Thank! I understood my mistake!

Comment by Isabella Siu (Inactive) [ 05/Feb/19 ]

pocoz The document is being skipped because cursor.Next() causes the cursor to go to the next document. Because of this, your first check to see if there are no documents is actually consuming the first document. Instead you can do something like this:

var terminalList []*D
for cursor.Next(ctx) {
   ... // decode and add to list
}
 
if err := cursor.Err() != nil {
    // Next returned false and there was an internal error
    return nil, err 
}
 
if len(terminalList) == 0 {
   return nil, mongo.ErrNoDocuments
}

Comment by John Daniels [ 05/Feb/19 ]

Hi @isabella.siu !
This error appears when I perform a check on the !cursor.Next after

 

defer cursor.Close(ctx)
 
if !cursor.Next(ctx) {
 return nil, mongo.ErrNoDocuments
}

 I apologize for not immediately indicating this in the code.

 

Comment by Isabella Siu (Inactive) [ 05/Feb/19 ]

Hi pocoz,

I tried to reproduce this with the following code, but was unable to. Does this match your usage, and if not, what's the difference?

func main() {func main() {
 var ctx = context.Background()
 client, _ := mongo.NewClient("mongodb://localhost:27017")
 client.Connect(ctx)
 db := client.Database("test")
 db.Collection("test").Drop(ctx)
 type D struct {    Terminal_id string }
 allIds := []string{"1","2","3","4","5"}
 for _, id := range allIds{
    _, err := db.Collection("test").InsertOne(ctx, D{Terminal_id: id})
    if err != nil {
       fmt.Println(err)
    }
 }
 ids := []string{"1","2","3"}
 filter := bson.M{"terminal_id": bson.M{"$in": ids}}
 cursor, err := db.Collection("test").Find(ctx, filter)
 if err != nil {  
    fmt.Println(err)
 }
 defer cursor.Close(ctx)
 var terminalList []*D
 for cursor.Next(ctx) {   
    var term *D
    err := cursor.Decode(&term)
    if err != nil {
       fmt.Println(err)
    }
    fmt.Println(*term)
    terminalList = append(terminalList, term)
 }}

Generated at Thu Feb 08 08:34:55 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.