filter

package module
v0.0.0-...-3387d28 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2024 License: MIT Imports: 4 Imported by: 0

README

mongo Query

mongo Query

mongo Query

mongo Query is a library that makes it easy to build MongoDB queries in Golang

Formulating requests with the MongoDB API is sometimes very difficult and error-prone. You have to build and nest untyped objects (bson.M, bson.D, ...). This will quickly become confusing and therefore difficult to read and maintain. mongo Query solves this problem with an easier to understand (DSL like) API.

For example, the following 'mongo Query' expression finds all documents in a MongoDB database where the array of 'amenities' has a size of 15 and the 'ListingUrl' equals '' and the 'pictureUrl' of the 'image' equals '':

Listing.Amenities.ArraySize(15).
  And(Listing.ListingUrl.Equals("<value>"),
      Listing.Images.PictureUrl.Equals("<value>"))

The (DSL-) queries are created with 'Filter structs' which can be generated using a commandline tool, which is also part of this project (see Generating filter types).

The API documentation for the filter structs can be found here. It is based on the 'native MongoDB query API'.

MongoDB API vs mongo Query

The following example shows how the queries differ between the MongoDB API and mongo Query. First of all, the struct with which the data is mapped in the MongoDB database:

type ListingAndReview struct {
	ListingUrl           string               `bson:"listing_url"`
	Name                 string               `bson:"name"`
	Bathrooms            primitive.Decimal128 `bson:"bathrooms"`
	Amenities            []string             `bson:"amenities"`
	Images               struct {
		ThumbnailUrl string `bson:"thumbnail_url"`
		MediumUrl    string `bson:"medium_url"`
		PictureUrl   string `bson:"picture_url"`
		XlPictureUrl string `bson:"xl_picture_url"`
	} `bson:"images"`
}

The data and data structures used in the examples come from a freely available Airbnb example database. You will find the complete ListingAndReview struct in this repo (it's only a subset in the sample above).

If you want to query the MongoDB collection and search for values with a specific ListingUrl and Name with the MongoDB-API, you have to write the following:

filter := bson.D{{"$and", []bson.D{
    {
        {"listing_url", "https://www.airbnb.com/rooms/10009999"},
    },
    {
        {"name", "Horto flat with small garden"},
    },
}}}

In this example you have to:

  • build the bson.D structure right (see the typ, slice, ...)
  • know about the MongoDB query operators ("$and")
  • know the BSON struct tags for all your fields ("listing_url", "name")
  • cross your fingers that no one will change the BSON mapping

In contrast, the same query with mongo Query looks like this:

filter := Listing.ListingUrl.Equals("https://www.airbnb.com/rooms/10009999").
	And(Listing.Name.Equals("Horto flat with small garden"))

It is:

  • readable
  • expressive
  • easy to write
  • independent of the bson.D structure
  • resistant to renaming BSON field names

How to use mongo Query

mongo Query uses its own simple API with Expression, Field and Operator types.

You can simply define a filter type for each struct you want to query. Instances of this filter types can than be used as parameter to the MongoDB API. They will automatically be marshalled as MongoDB bson.D objects.

You can generate this filter types with a generator which is also part of this project! See below.

type ListingFilter struct {
	ListingUrl Field
	Name       Field
	Bedrooms   Field
	Amenities  ArrayField
	Images     ImagesFilter
}

type ImagesFilter struct {
	ThumbnailUrl Field
	MediumUrl    Field
	PictureUrl   Field
	XlPictureUrl Field
}

var Listing = ListingFilter{
    ListingUrl: Field("listing_url"),
    Name:       Field("name"),
    Bedrooms:   Field("bedrooms"),
    Amenities:  ArrayField("amenities"),
    Images: ImagesFilter{
        ThumbnailUrl: Field("images.thumbnail_url"),
        MediumUrl:    Field("images.medium_url"),
        PictureUrl:   Field("images.picture_url"),
        XlPictureUrl: Field("images.xl_picture_url"),
    },
}

And then you can use the filter and query data via the MongoDB API:

...
filter := Listing.ListingUrl.Equals("https://www.airbnb.com/rooms/10009999")
collection := client.Database("airbnb").Collection("listingsAndReviews")
cursor, err := collection.Find(ctx, filter)
...

or with embedded documents...

...
filter := Listing.Amenities.ArraySize(15).
    And(Listing.ListingUrl.Equals("<value>"),
        Listing.Images.PictureUrl.Equals("<value>"))

collection := client.Database("airbnb").Collection("listingsAndReviews")
cursor, err := collection.Find(ctx, filter)
...

You will find a complete sample within the unit tests of this project.

Generating filter types

Defining filter types is easy. Just use the generator which is also included in the project. Install it via go install and use it (see an example here):

go install github.com/sourcefellows/mongo-query/cmd/mongo-query-gen@latest
kkoehler@project$ mongo-query-gen 
no input file given
  -in string
        path to file with Golang structs
  -only string
        list of struct names - only given struct names will be used for code generation
  -outDir string
        path to output directory - a subdirectory "filter" will be generated automatically

For example:

mongo-query-gen -in Types.go -outDir .

Samples from MongoDB manual

  • Query embedded documents (Specify Equality Match on a Nested Field) (see here or local impl)
//MongoDB API
err = findWithFilter(ctx, collection, bson.D{{"size.uom", "in"}})
//mongo Query
err = findWithFilter(ctx, collection, InventoryFilter.Size.Uom.Equals("in"))
//MongoDB API
err = findWithFilter(ctx, collection, bson.D{
    {"size.h", bson.D{
        {"$lt", 15},
    }},
    {"size.uom", "in"},
    {"status", "D"},
})
//mongo Query
err = findWithFilter(ctx, collection,
    InventoryFilter.Size.H.Lt(15).
        And(InventoryFilter.Size.Uom.Equals("in"),
            InventoryFilter.Status.Equals("D")))

Documentation

Index

Examples

Constants

View Source
const RegexpOptionCaseInsensitivity = RegexpOption("i")

RegexpOptionCaseInsensitivity case insensitivity to match upper and lower cases.

View Source
const RegexpOptionExtended = RegexpOption("x")

RegexpOptionExtended defines "extended" capability to ignore all white space characters in the pattern unless escaped or included in a character class. Additionally, it ignores characters in-between and including an un-escaped hash/pound (#) character and the next new line, so that you may include comments in complicated patterns. This only applies to data characters; white space characters may never appear within special character sequences in a pattern.

The x option does not affect the handling of the VT character (i.e. code 11).

View Source
const RegexpOptionMatchAll = RegexpOption("s")

RegexpOptionMatchAll allows the dot character (i.e. .) to match all characters including newline characters.

View Source
const RegexpOptionMultiline = RegexpOption("M")

RegexpOptionMultiline is for patterns that include anchors (i.e. ^ for the start, $ for the end), match at the beginning or end of each line for strings with multiline values. Without this option, these anchors match at beginning or end of the string. For an example, see Multiline Match for Lines Starting with Specified Pattern.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArrayField

type ArrayField string

ArrayField represents an array field in a BSON document.

func (ArrayField) ArrayContainsAll

func (f ArrayField) ArrayContainsAll(val ...any) Expression

ArrayContainsAll matches all documents where the given values are in the array.

func (ArrayField) ArrayContainsElement

func (f ArrayField) ArrayContainsElement(queries ...QueryOperator) Expression

func (ArrayField) ArrayContainsElementMatchesExpression

func (f ArrayField) ArrayContainsElementMatchesExpression(expressions ...Expression) Expression

ArrayContainsElementMatchesExpression matches all documents which meet the EXACT expression.

func (ArrayField) ArrayContainsExact

func (f ArrayField) ArrayContainsExact(val ...any) Expression

ArrayContainsExact matches all documents where ONLY the given values are in the array.

func (ArrayField) ArraySize

func (f ArrayField) ArraySize(size int) Expression

type Expression

type Expression struct {
	// contains filtered or unexported fields
}

Expression represents a MongoDB Expression for a specific field.

func (Expression) And

func (e Expression) And(e2 ...Expression) Expression

And represents a logical query operation for 'and' condition. It takes one or more Expression(s) and selects the documents that satisfy all the expressions.

Example
Filter := struct {
	Status Field
	Size   struct {
		H   Field
		Uom Field
	}
}{
	Status: Field("status"),
	Size: struct {
		H   Field
		Uom Field
	}{
		Uom: Field("size.uom"),
		H:   Field("size.h"),
	},
}

f1 := Filter.Size.H.Lt(15).And(Filter.Size.Uom.Equals("in"))

fmt.Println(f1)
Output:

bson.D{{"$and", []bson.D{bson.D{{"size.h", bson.D{{"$lt", 15}}}}, bson.D{{"size.uom", "in"}}}}}
Example (WithEquals)
Filter := struct {
	Status Field
	Size   struct {
		H   Field
		Uom Field
	}
}{
	Status: Field("status"),
	Size: struct {
		H   Field
		Uom Field
	}{
		Uom: Field("size.uom"),
		H:   Field("size.h"),
	},
}

f1 := Filter.Size.H.Lt(15).And(Filter.Size.Uom.Equals("in"), Filter.Status.Equals("D"))

fmt.Println(f1)
Output:

bson.D{{"$and", []bson.D{bson.D{{"size.h", bson.D{{"$lt", 15}}}}, bson.D{{"size.uom", "in"}}, bson.D{{"status", "D"}}}}}

func (Expression) MarshalBSON

func (e Expression) MarshalBSON() ([]byte, error)

MarshalBSON serializes the Expression to BSON data.

func (Expression) Or

func (e Expression) Or(e2 ...Expression) Expression

Or represents a logical query operation for 'or' condition. It takes one or more Expression(s) and selects the documents that satisfy at least one expression.

Example
Filter := struct {
	Status Field
	Size   struct {
		H   Field
		Uom Field
	}
}{
	Status: Field("status"),
	Size: struct {
		H   Field
		Uom Field
	}{
		Uom: Field("size.uom"),
		H:   Field("size.h"),
	},
}

f1 := Filter.Size.H.Lt(15).Or(Filter.Size.Uom.Equals("in"))

fmt.Println(f1)
Output:

bson.D{{"$or", []bson.D{bson.D{{"size.h", bson.D{{"$lt", 15}}}}, bson.D{{"size.uom", "in"}}}}}

func (Expression) String

func (e Expression) String() string

type Field

type Field string

Field represents a single field in a BSON document.

func (Field) CurrentDate

func (f Field) CurrentDate() UpdateExpression

CurrentDate sets the value of a field to the current date, either as a Date or a timestamp.

func (Field) Equals

func (f Field) Equals(value any) Expression

Equals represents a query operation for 'equals' comparison.

Example
Filter := struct {
	Size struct {
		Uom Field
	}
}{
	Size: struct {
		Uom Field
	}{
		Uom: Field("size.uom"),
	},
}

f1 := Filter.Size.Uom.Equals("in")

fmt.Println(f1)
Output:

bson.D{{"size.uom", "in"}}

func (Field) Exists

func (f Field) Exists() Expression

Exists represents an element query operation to check if a field exists. It Matches documents that have the specified field.

func (Field) GreaterThan

func (f Field) GreaterThan(value any) Expression

GreaterThan represents a query operation for 'greater than' comparison.

func (Field) GreaterThanOrEquals

func (f Field) GreaterThanOrEquals(value any) Expression

GreaterThanOrEquals represents a query operation for 'greater than or equals' comparison.

func (Field) Gt

func (f Field) Gt(value any) Expression

Gt represents a query operation for 'greater than' comparison.

func (Field) Gte

func (f Field) Gte(value any) Expression

Gte represents a query operation for 'greater than or equals' comparison.

func (Field) In

func (f Field) In(value ...any) Expression

In represents a query operation for 'in' comparison. The operator selects the documents where the value of a field equals any value in the specified parameter(s).

func (Field) Inc

func (f Field) Inc(value any) UpdateExpression

Inc increments the field by a specified value.

func (Field) LessThan

func (f Field) LessThan(value any) Expression

LessThan represents a query operation for 'less than' comparison.

func (Field) LessThanOrEqual

func (f Field) LessThanOrEqual(value any) Expression

LessThanOrEqual represents a query operation for 'less than or equals' comparison.

func (Field) Lt

func (f Field) Lt(value any) Expression

Lt represents a query operation for 'less than' comparison.

Example
Filter := struct {
	Size struct {
		H Field
	}
}{
	Size: struct {
		H Field
	}{
		H: Field("size.h"),
	},
}

f1 := Filter.Size.H.Lt(15)

fmt.Println(f1)
Output:

bson.D{{"size.h", bson.D{{"$lt", 15}}}}

func (Field) Lte

func (f Field) Lte(value any) Expression

Lte represents a query operation for 'less than or equal' comparison.

func (Field) Max

func (f Field) Max(value any) UpdateExpression

Max updates the value of the field to a specified value if the specified value is greater than the current value of the field.

The '$max operator', which is used internally, can compare values of different types, using the BSON comparison order.

func (Field) Min

func (f Field) Min(value any) UpdateExpression

Min updates the value of the field to a specified value if the specified value is less than the current value of the field.

The '$min operator', which is used internally, can compare values of different types, using the BSON comparison order.

func (Field) Mul

func (f Field) Mul(value any) UpdateExpression

Mul multiplies the value of the field by a number.

The field to update must contain a numeric value.

func (Field) Ne

func (f Field) Ne(value any) Expression

Ne represents a query operation for 'not equals' comparison.

func (Field) NotEquals

func (f Field) NotEquals(value any) Expression

NotEquals represents a query operation for 'not equals' comparison.

func (Field) NotExists

func (f Field) NotExists() Expression

NotExists represents an element query operation to check if a field does not exist. It Matches documents that do not have the specified field.

func (Field) NotIn

func (f Field) NotIn(value ...any) Expression

NotIn represents a query operation for 'not in' comparison. The operator selects the documents where:

  • the specified field value is not in the specified array or
  • the specified field does not exist.

func (Field) Regex

func (f Field) Regex(val string, opts ...RegexpOption) Expression

Regex represents an element query operation which has regular expression capabilities for pattern matching strings in queries.

Example
Filter := struct {
	Status Field
	Size   struct {
		H   Field
		Uom Field
	}
}{
	Status: Field("status"),
	Size: struct {
		H   Field
		Uom Field
	}{
		Uom: Field("size.uom"),
		H:   Field("size.h"),
	},
}

f1 := Filter.Size.Uom.Regex("i.*")

fmt.Println(f1)
Output:

bson.D{{"size.uom", bson.D{{"$regex", "i.*"}}}}
Example (WithOptions)
Filter := struct {
	Status Field
	Size   struct {
		H   Field
		Uom Field
	}
}{
	Status: Field("status"),
	Size: struct {
		H   Field
		Uom Field
	}{
		Uom: Field("size.uom"),
		H:   Field("size.h"),
	},
}

f1 := Filter.Size.Uom.Regex("i.*", RegexpOptionCaseInsensitivity)

fmt.Println(f1)
Output:

bson.D{{"size.uom", bson.D{{"$regex", "i.*"},{"$options", "i"}}}}

func (Field) Rename

func (f Field) Rename(value Field) UpdateExpression

Rename updates the name of the field.

The new field name must differ from the existing field name.

func (Field) Set

func (f Field) Set(value any) UpdateExpression

Set replaces the value of the field with the specified value.

Example
expression := Listing.ListingUrl.Set("http://www.source-fellows.com")

fmt.Println(expression)
Output:

bson.D{{"$set", bson.D{{"listing_url", "http://www.source-fellows.com"}}}}
Example (WithCondition)
expression := Listing.ListingUrl.Set("http://www.source-fellows.com").And(Listing.Name.Set("Horst"))

fmt.Println(expression)
Output:

bson.D{{"$set", bson.D{{"listing_url", "http://www.source-fellows.com"},{"name", "Horst"}}}}

func (Field) Unset

func (f Field) Unset() UpdateExpression

Unset deletes the particular field.

type LogicalOperator

type LogicalOperator struct {
	// contains filtered or unexported fields
}

LogicalOperator is used to represent a logical MongoDB Operator.

type QueryOperator

type QueryOperator struct {
	// contains filtered or unexported fields
}

QueryOperator is used to represent a MongoDB Query Operator.

func All

func All(val ...any) QueryOperator

All builds a simple QueryOperator for MongoDB operator "$all". "all"

func Equals

func Equals(value any) QueryOperator

Equals builds a simple QueryOperator for MongoDB operator "$eq".

func Exists

func Exists() QueryOperator

Exists builds a simple QueryOperator for MongoDB operator "$exists". "exists"

func Gt

func Gt(value any) QueryOperator

Gt builds a simple QueryOperator for MongoDB operator "$gt".

func Gte

func Gte(value any) QueryOperator

Gte builds a simple QueryOperator for MongoDB operator "$gte". "greater or equals"

func In

func In(value ...any) QueryOperator

In builds a simple QueryOperator for MongoDB operator "$in". "in"

func Lt

func Lt(value any) QueryOperator

Lt builds a simple QueryOperator for MongoDB operator "$lt". "Less than"

func Lte

func Lte(value any) QueryOperator

Lte builds a simple QueryOperator for MongoDB operator "$lte". "Less than or equals"

func Ne

func Ne(value any) QueryOperator

Ne builds a simple QueryOperator for MongoDB operator "$ne". "not equals"

func NotExists

func NotExists() QueryOperator

NotExists builds a simple QueryOperator for MongoDB operator "$exists". "not exists"

func NotIn

func NotIn(value ...any) QueryOperator

NotIn builds a simple QueryOperator for MongoDB operator "$nin". "in"

func Regex

func Regex(val string) QueryOperator

Regex buidls a regular expression capabilities for pattern matching strings in queries.

func Size

func Size(size int) QueryOperator

Size builds a simple QueryOperator for MongoDB operator "$size". "size of array"

type RegexpOption

type RegexpOption string

type UpdateExpression

type UpdateExpression struct {
	// contains filtered or unexported fields
}

func (UpdateExpression) And

func (UpdateExpression) MarshalBSON

func (ue UpdateExpression) MarshalBSON() ([]byte, error)

func (UpdateExpression) String

func (ue UpdateExpression) String() string

type UpdateOperator

type UpdateOperator struct {
	// contains filtered or unexported fields
}

Directories

Path Synopsis
cmd
examples
generator/filter
Code generated by monGo-Query.
Code generated by monGo-Query.

Jump to

Keyboard shortcuts

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