mgs

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2024 License: MIT Imports: 10 Imported by: 2

README

Go Reference GitHub release (with filter) Go Report codecov MIT License

Mongo Golang Search

Mongo Golang Search provides a query language to a MongoDB database.
Explore the docs

Report Bug · Request Feature


Mongo Golang Search (mgs)

Content index

What is this?

Mongo Golang Search provides a simple query language to perform advanced searches for your collections in MongoDB.

You could also use Mongo Golang Search to searching, sorting, pagination and combining logical operators.

Getting Started

Installation

The recommended way to get started using the Mongo Golang Search is by using Go modules to install the dependency in your project. This can be done either by importing packages from github.com/ajclopez/mgs and having the build step install the dependency or by explicitly running

go get github.com/ajclopez/mgs

Usage

To get started with mgs, import the mgs package and implement the Primitives ObjectID function which is used to convert strings to ObjectID.

type Primitives struct{}

func (primitives *Primitives) ObjectID(oidStr string) (interface{}, error) {
	return ObjectID() // invoke ObjectID from MongoDB Driver
}

Then create an instance of QueryHandler:

queryHandler := mgs.NewQueryHandler(&Primitives{})

Finally use a mgs.MongoGoSearch function:

queryHandler.MongoGoSearch(query string, opts *FindOptions)
Arguments

query: query string part of the requested API URL.

opts: object for advanced configuration See below [optional].

Using mgs.MongoGoSearch function with mongo-go-driver library to filter, sort, limit and skip in MongoDB:

import (
    "context"

    "github.com/ajclopez/mgs"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Primitives struct{}

func (primitives *Primitives) ObjectID(oidStr string) (interface{}, error) {
	return primitive.ObjectIDFromHex(oidStr)
}

queryHandler := mgs.NewQueryHandler(&Primitives{})

opts := mgs.FindOption()
result, err := queryHandler.MongoGoSearch(query, opts)

...

findOpts := options.Find()
findOpts.SetLimit(result.Limit)
findOpts.SetSkip(result.Skip)
findOpts.SetSort(result.Sort)
findOpts.SetProjection(result.Projection)

cur, err := collection.Find(context.TODO(), result.Filter, findOpts)

...

Using optional configurations:

import (
    "context"

    "github.com/ajclopez/mgs"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Primitives struct{}

func (primitives *Primitives) ObjectID(oidStr string) (interface{}, error) {
	return primitive.ObjectIDFromHex(oidStr)
}

queryHandler := mgs.NewQueryHandler(&Primitives{})

opts := mgs.FindOption()
opts.SetCaster(map[string]mgs.CastType{
	"mobile": mgs.STRING,
})
opts.SetMaxLimit(1000)
opts.SetDefaultLimit(10)
result, err := queryHandler.MongoGoSearch(query, opts)

...

findOpts := options.Find()
findOpts.SetLimit(result.Limit)
findOpts.SetSkip(result.Skip)
findOpts.SetSort(result.Sort)
findOpts.SetProjection(result.Projection)

cur, err := collection.Find(context.TODO(), result.Filter, findOpts)

...
Example

A request of the form:

'employees?status=sent&date>2020-01-06T14:00:00.000Z&author.firstname=Jhon&skip=50&limit=100&sort=-date&fields=id,date';

Is translated to:

Query{
    Filter: map[string]interface{}{
        "author.firstname":     "John",
        "date":                 map[string]interface{}{"$gt": "2020-01-06T14:00:00.000Z"},
        "status":               "SENT",
    },
    Sort:  map[string]int{
        "date": 1,
        "id": 1
    },
    Limit: 100,
    Skip:  50,
}

Supported features

Filtering
Operator URI Example
$eq key=val type=public
$ne key!=val status!=SENT
$gt key>val price>5
$gte key>=val price>=9
$lt key<val date<2020-01-01T14:00:00.000Z
$lte key<=val priority<=-5
$in key=val1,val2 status=QUEUED,DEQUEUED
$nin key!=val1,val2 status!=QUEUED,DEQUEUED
$exists key email
$exists !key !email
$regex key=/value/<opts> email=/@gmail\.com$/
$regex key!=/value/<opts> phone!=/^58/
Pagination

Useful to limit the number of records returned.

  • Operator keys are skip and limit.
  • Use limit operator to limit the number of records returned.
  • Use skip operator to skip the specified number of records.
skip=20&limit=10
Sorting

Useful to sort returned records.

  • Operator key is sort.
  • It accepts a comma-separated list of fields.
  • Use - prefixes to sort in descending order.
  • Use + prefixes to sort in ascedending order.
sort=id,-date
Projection

Useful to limit fields to return in each records.

  • Operator key is fields.
  • It accepts a comma-separated list of fields.
fields=firstname,lastname,phone,email

Note:

  • The _id field (returned by default).
Advanced queries

For more advanced usage (and, or logic operations), pass query filter as string with the logical operations, for example:

filter=(country=Mexico OR country=Spain) and gender=female
What operations are possible?
  • Filtering operations.
  • The AND/and operator.
  • The OR/or operator.
  • Parenthesis can be used for grouping.

Available options

You can use advanced options:

opts := mgs.FindOption()
opts.SetCaster(map[string]mgs.CastType{
	"mobile": mgs.STRING,
})
opts.SetMaxLimit(100)
opts.SetDefaultLimit(10)
  • FindOption creates a new FindOptions instance.
  • SetCaster object to specify custom casters, key is the caster name, and value is a type (BOOLEAN, NUMBER, PATTERN, DATE, STRING).
  • SetDefaultLimit which contains custom value to return records.
  • SetMaxLimit which contains custom value to return a maximum of records.
Customize limit value

You can specify your own maximum or default limit value.

  • defaultLimit: custom value to return records.
  • maxLimit: custom value to return a maximum of records.
opts := mgs.FindOption()
opts.SetMaxLimit(1000)
opts.SetDefaultLimit(10)

result, err := mgs.MongoGoSearch("city=Madrid&skip=10&limit=1000", opts)
Specify casting per param keys

You can specify how query parameter values are casted by passing an object.

  • casters: object which map keys to casters.
opts := mgs.FindOption()
opts.SetCaster(map[string]mgs.CastType{
	"key1": mgs.STRING,
    "key2": mgs.NUMBER,
    "key3": mgs.STRING,
    "key4": mgs.BOOLEAN
})

result, err := mgs.MongoGoSearch("key1=VALUE&key2=10&key3=20&key4=true", opts)

Contributing

Should you like to provide any feedback, please open up an Issue, I appreciate feedback and comments. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing-feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This software is released under the MIT license. See LICENSE for more information.

Documentation

Index

Constants

View Source
const DATE_FORMAT = "2006-01-02T15:04:05.000Z"
View Source
const OPERATOR_PATTERN string = "(?P<Prefix>!?)(?P<Key>[^><!=]+)(?P<Operator>[><]=?|!?=|)(?P<Value>.*)"
View Source
const REGEX_PATTERN string = "^\\/(?P<Pattern>.*)\\/(?P<Option>[igm]*)$"

Variables

View Source
var (
	// ErrUnescapeCharacters is returned when cannot converter an unescape string
	ErrUnescapeCharacters = errors.New("unescape characters")
	// ErrValueNoMatch is returned when the converter cannot match a string to
	// an unsigned integer.
	ErrValueNoMatch = errors.New("value does not match")
	// ErrQueryVisitor
	ErrQueryVisitor = errors.New("context does not exists")
)

Functions

func Convert

func Convert(criteria SearchCriteria, qh *QueryHandler) map[string]interface{}

Convert converts the criteria value to a MongoDB query

func GetOperatorPattern

func GetOperatorPattern() *regexp.Regexp

GetOperatorPattern gets operator RegExp pattern

func GetRegexPattern

func GetRegexPattern() *regexp.Regexp

GetRegexPattern gets RegExp pattern

func ParseValue

func ParseValue(value string, qh *QueryHandler, cast *CastType) interface{}

ParseValue converts a string to a data type

Types

type CastType

type CastType int
const (
	NUMBER CastType = iota + 1
	DATE
	BOOLEAN
	PATTERN
	STRING
)

list of allowed cast type.

type FindOptions

type FindOptions struct {
	// Caster map to set object type on values by key (BOOLEAN, NUMBER, PATTERN, DATE, STRING).
	Caster *map[string]CastType
	// DefaultLimit default value for limit key.
	DefaultLimit *int64
	// MaxLimit maximum value for limit key.
	MaxLimit *int64
}

FindOptions is a structure that allows to use advanced options.

func FindOption

func FindOption() *FindOptions

FindOption creates a new FindOptions instance.

func (*FindOptions) SetCaster

func (f *FindOptions) SetCaster(m map[string]CastType) *FindOptions

SetCaster sets the value for the object type on values by key.

func (*FindOptions) SetDefaultLimit

func (f *FindOptions) SetDefaultLimit(i int64) *FindOptions

SetDefaultLimit sets the value for the default value for limit key.

func (*FindOptions) SetMaxLimit

func (f *FindOptions) SetMaxLimit(i int64) *FindOptions

SetMaxLimit sets the value for the maximum value for limit key.

type Primitives added in v1.1.0

type Primitives interface {
	ObjectID(val string) (oid interface{}, err error)
}

Primitives defines methods to convert to specific types.

type Query

type Query struct {
	// Filter is a document containing query operators.
	Filter map[string][]interface{}
	// Sort is a document specifying the order in which documents should be returned.
	Sort map[string]int
	// Limit is the maximum number of documents to return.
	Limit int64
	// Skip is a number of documents to be skipped.
	Skip int64
	// Projection is the limit fields to return in each records.
	Projection map[string]int
}

Query is a structure that holds information about DB request.

type QueryHandler added in v1.1.0

type QueryHandler struct {
	Primitives Primitives
}

QueryHandler handles query construction for MongoDB.

func NewQueryHandler added in v1.1.0

func NewQueryHandler(primitives Primitives) *QueryHandler

NewQueryHandler creates a new QueryHandler instance.

func (*QueryHandler) MongoGoSearch added in v1.1.0

func (qh *QueryHandler) MongoGoSearch(query string, opts *FindOptions) (Query, error)

MongoGoSearch converts query into a MongoDB query object.

type Regex

type Regex struct {
	// Pattern is a string contains regex pattern should be used.
	Pattern string
	// Opetion is a string contains regex options should be used.
	Option string
}

Regex is a structure that holds RegExp specification.

type SearchCriteria

type SearchCriteria struct {
	// Prefix is a bool that allows to check that the search criteria contain prefixes.
	Prefix bool
	// key is a string that allows the key to be identified in the search criteria.
	Key string
	// Operation is a structure that containing operator type.
	Operation SearchOperator
	// Value is a string that allows the value to be identified in the search criteria.
	Value string
	// Caster is a cast type value.
	Caster *CastType
}

SearchCriteria is a structure that holds search criteria specification.

func CriteriaParser added in v1.0.1

func CriteriaParser(condition string, caster *map[string]CastType) SearchCriteria

CriteriaParser build criteria from a condition expression

func Parse

func Parse(query string, caster *map[string]CastType) []SearchCriteria

Parse parses a given url query.

type SearchOperator

type SearchOperator int
const (
	EQUAL SearchOperator = iota + 1
	NOT_EQUAL
	GREATER_THAN
	GREATER_THAN_EQUAL
	LESS_THAN
	LESS_THAN_EQUAL
	EXISTS
)

list of allowed operators.

func (SearchOperator) GetOperation

func (s SearchOperator) GetOperation(input string) SearchOperator

GetOperation allows get operation type to filter query

func (SearchOperator) String

func (s SearchOperator) String() string

String gets operator string.

type Visitor added in v1.0.1

type Visitor struct {
	*parser.BaseQueryVisitor
	QueryHandler *QueryHandler
	Caster       *map[string]CastType
}

func NewGeneratorVisitor added in v1.0.1

func NewGeneratorVisitor(qh *QueryHandler, caster *map[string]CastType) *Visitor

func (*Visitor) Visit added in v1.0.1

func (v *Visitor) Visit(tree antlr.ParseTree) interface{}

func (*Visitor) VisitAtomQuery added in v1.0.1

func (v *Visitor) VisitAtomQuery(ctx *parser.AtomQueryContext) interface{}

func (*Visitor) VisitCriteria added in v1.0.1

func (v *Visitor) VisitCriteria(ctx *parser.CriteriaContext) interface{}

func (*Visitor) VisitInput added in v1.0.1

func (v *Visitor) VisitInput(ctx *parser.InputContext) interface{}

func (*Visitor) VisitOpQuery added in v1.0.1

func (v *Visitor) VisitOpQuery(ctx *parser.OpQueryContext) interface{}

func (*Visitor) VisitPriorityQuery added in v1.0.1

func (v *Visitor) VisitPriorityQuery(ctx *parser.PriorityQueryContext) interface{}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL