从错误信息mongo: no documents in result来看,问题在于查询没有返回任何文档。这通常发生在查询条件不匹配数据库中的任何记录时。以下是可能导致此问题的原因及解决方案:
1. 检查查询条件
确保查询条件与数据库中的数据匹配。使用FindOne时,如果没有匹配的文档,会返回此错误。
// 示例:检查查询条件
filter := bson.M{"username": username, "password": password}
var result bson.M
err := collection.FindOne(context.Background(), filter).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
// 没有找到匹配的文档
log.Println("No user found with provided credentials")
return
}
log.Fatal(err)
}
2. 添加调试日志
在查询前后添加详细的日志,查看实际执行的查询条件:
// 添加调试日志
log.Printf("Querying with filter: %+v", filter)
var user User
err := collection.FindOne(ctx, filter).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
log.Printf("No document found for filter: %+v", filter)
// 返回适当的错误响应
return
}
log.Printf("Database error: %v", err)
return
}
log.Printf("Found user: %+v", user)
3. 检查数据库连接和数据
确保:
- MongoDB服务正在运行
- 连接到了正确的数据库和集合
- 集合中存在符合条件的数据
// 验证集合是否存在数据
count, err := collection.CountDocuments(ctx, bson.M{})
if err != nil {
log.Printf("Error counting documents: %v", err)
return
}
log.Printf("Total documents in collection: %d", count)
// 查看所有用户数据(仅用于调试)
cursor, err := collection.Find(ctx, bson.M{})
if err != nil {
log.Printf("Error finding all documents: %v", err)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var doc bson.M
if err := cursor.Decode(&doc); err != nil {
log.Printf("Error decoding document: %v", err)
continue
}
log.Printf("Document in collection: %v", doc)
}
4. 处理查询结果
正确处理ErrNoDocuments错误:
func login(username, password string) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
filter := bson.M{
"username": username,
"password": bson.M{"$exists": true}, // 确保字段存在
}
var user User
err := collection.FindOne(ctx, filter).Decode(&user)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
// 没有找到用户
return fmt.Errorf("invalid credentials")
}
return fmt.Errorf("database error: %w", err)
}
// 验证密码(建议使用哈希比较)
if !checkPasswordHash(password, user.PasswordHash) {
return fmt.Errorf("invalid credentials")
}
return nil
}
5. 检查字段名大小写
确保查询中的字段名与数据库中的字段名完全匹配(包括大小写):
// 使用正确的字段名
filter := bson.M{
"UserName": username, // 注意大小写
"Password": password,
}
6. 完整示例代码
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
Username string `bson:"username"`
Password string `bson:"password"`
}
func main() {
// 连接MongoDB
client, err := mongo.Connect(context.Background(),
options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
log.Fatal(err)
}
collection := client.Database("testdb").Collection("users")
// 登录函数
err = login(collection, "testuser", "testpass")
if err != nil {
log.Printf("Login failed: %v", err)
}
}
func login(collection *mongo.Collection, username, password string) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
filter := bson.M{"username": username}
log.Printf("Executing query with filter: %v", filter)
var user User
err := collection.FindOne(ctx, filter).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
log.Printf("User '%s' not found in database", username)
return fmt.Errorf("user not found")
}
return err
}
log.Printf("Found user: %+v", user)
// 验证密码
if user.Password != password {
return fmt.Errorf("invalid password")
}
log.Println("Login successful")
return nil
}
主要问题很可能是查询条件不匹配数据库中的实际数据。建议先使用MongoDB Compass或mongo shell验证数据库中的实际数据,然后调整查询条件。