Mike Schwörer
ae43cbb623
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 55s
88 lines
2.9 KiB
Go
88 lines
2.9 KiB
Go
package wmo
|
|
|
|
import (
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
ct "gogs.mikescher.com/BlackForestBytes/goext/cursortoken"
|
|
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
|
)
|
|
|
|
func CreatePagination[TData any](coll *Coll[TData], token ct.CursorToken, fieldPrimary string, sortPrimary ct.SortDirection, fieldSecondary *string, sortSecondary *ct.SortDirection, pageSize *int) ([]bson.D, error) {
|
|
|
|
cond := bson.A{}
|
|
sort := bson.D{}
|
|
|
|
valuePrimary, err := coll.getTokenValueAsMongoType(token.ValuePrimary, fieldPrimary)
|
|
if err != nil {
|
|
return nil, exerr.Wrap(err, "failed to get (primary) token-value as mongo-type").Build()
|
|
}
|
|
|
|
if sortPrimary == ct.SortASC {
|
|
// We sort ASC on <field> - so we want all entries newer ($gt) than the $primary
|
|
cond = append(cond, bson.M{fieldPrimary: bson.M{"$gt": valuePrimary}})
|
|
sort = append(sort, bson.E{Key: fieldPrimary, Value: +1})
|
|
} else if sortPrimary == ct.SortDESC {
|
|
// We sort DESC on <field> - so we want all entries older ($lt) than the $primary
|
|
cond = append(cond, bson.M{fieldPrimary: bson.M{"$lt": valuePrimary}})
|
|
sort = append(sort, bson.E{Key: fieldPrimary, Value: -1})
|
|
}
|
|
|
|
if fieldSecondary != nil && sortSecondary != nil && *fieldSecondary != fieldPrimary {
|
|
|
|
valueSecondary, err := coll.getTokenValueAsMongoType(token.ValueSecondary, *fieldSecondary)
|
|
if err != nil {
|
|
return nil, exerr.Wrap(err, "failed to get (secondary) token-value as mongo-type").Build()
|
|
}
|
|
|
|
if *sortSecondary == ct.SortASC {
|
|
|
|
// the conflict-resolution condition, for entries with the _same_ <field> as the $primary we take the ones with a greater $secondary (= newer)
|
|
cond = append(cond, bson.M{"$and": bson.A{
|
|
bson.M{fieldPrimary: valuePrimary},
|
|
bson.M{*fieldSecondary: bson.M{"$gt": valueSecondary}},
|
|
}})
|
|
|
|
sort = append(sort, bson.E{Key: fieldPrimary, Value: +1})
|
|
|
|
} else if *sortSecondary == ct.SortDESC {
|
|
|
|
// the conflict-resolution condition, for entries with the _same_ <field> as the $primary we take the ones with a smaller $secondary (= older)
|
|
cond = append(cond, bson.M{"$and": bson.A{
|
|
bson.M{fieldPrimary: valuePrimary},
|
|
bson.M{*fieldSecondary: bson.M{"$lt": valueSecondary}},
|
|
}})
|
|
|
|
sort = append(sort, bson.E{Key: fieldPrimary, Value: -1})
|
|
|
|
}
|
|
}
|
|
|
|
pipeline := make([]bson.D, 0, 3)
|
|
|
|
if token.Mode == ct.CTMStart {
|
|
|
|
// no gt/lt condition
|
|
|
|
} else if token.Mode == ct.CTMNormal {
|
|
|
|
pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.M{"$or": cond}}})
|
|
|
|
} else if token.Mode == ct.CTMEnd {
|
|
|
|
// false
|
|
pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.M{"$expr": bson.M{"$eq": bson.A{"1", "0"}}}}})
|
|
|
|
} else {
|
|
|
|
return nil, exerr.New(exerr.TypeInternal, "unknown ct mode: "+string(token.Mode)).Any("token.Mode", token.Mode).Build()
|
|
|
|
}
|
|
|
|
pipeline = append(pipeline, bson.D{{Key: "$sort", Value: sort}})
|
|
|
|
if pageSize != nil {
|
|
pipeline = append(pipeline, bson.D{{Key: "$limit", Value: int64(*pageSize + 1)}})
|
|
}
|
|
|
|
return pipeline, nil
|
|
}
|