alex
alex

Reputation: 608

Golang mongoDB search document

I started to learn mongoDB and I'm trying to search users by a few parameters, username, firstname, lastname. In the example below I can search users by username and I get data.

// Search users
func (r *Mongo) Search(ctx context.Context, query string) ([]*User, error) {
    findOptions := options.Find()
    // Sort by `username` field descending
    findOptions.SetSort(bson.D{{"username", -1}})

    filter := bson.M{"username": bson.M{"$regex": query, "$options": "i"}}
    cursor, err := r.col.Find(ctx, filter, findOptions)
    if err != nil {
        return nil, err
    }

    var results []*User
    if err = cursor.All(ctx, &results); err != nil {
        return nil, err
    }

    return results, nil
}

The following example search multiple parameters, but the result is empty.

// Search users
func (r *Mongo) Search(ctx context.Context, query string) ([]*User, error) {
    findOptions := options.Find()
    // Sort by `username` field descending
    findOptions.SetSort(bson.D{{"username", -1}})

    filter := bson.M{
        "username": bson.M{"$regex": query, "$options": "i"},
        "$or": []interface{}{
            bson.M{"firstname": bson.M{"$regex": query, "$options": "i"}},
            bson.M{"lastname": bson.M{"$regex": query, "$options": "i"}},
        },
    }

    // filter := bson.M{"username": bson.M{"$regex": query, "$options": "i"}}
    cursor, err := r.col.Find(ctx, filter, findOptions)
    if err != nil {
        return nil, err
    }

    var results []*User
    if err = cursor.All(ctx, &results); err != nil {
        return nil, err
    }

    return results, nil
}

Question, how can I search by multiple parameters(use $or)?

And Is this search option optimal and correct, or is there a more correct search option in MongoDB, analog of LIKE from SQL?

Thanks in advance for the answer.

Upvotes: 1

Views: 220

Answers (1)

alex
alex

Reputation: 608

If someone needs to search by several parameters, this might be useful: I put the filter assembly in a separate method

func (r *Mongo) queryBuilderFilter(query *Query) bson.M {
    var andFilters []bson.M

    if query.Query != "" {
        orFilters := []bson.M{
            {
                "username": bson.M{"$regex": primitive.Regex{Pattern: "^" + query.Query + "*", Options: "i"}},
            },
            {
                "firstname": bson.M{"$regex": primitive.Regex{Pattern: "^" + query.Query + "*", Options: "i"}},
            },
            {
                "lastname": bson.M{"$regex": primitive.Regex{Pattern: "^" + query.Query + "*", Options: "i"}},
            },
        }
        andFilters = append(andFilters, bson.M{"$or": orFilters})
    }

    if len(andFilters) == 0 {
        // Handle empty and, since there must be one item.
        return bson.M{}
    }
    return bson.M{"$and": andFilters}
}

Upvotes: 1

Related Questions