combine query params filters

This commit is contained in:
Mariano 2024-03-25 14:06:24 -03:00
parent 91fbd1cdaf
commit 5b03c9e899
4 changed files with 100 additions and 76 deletions

View File

@ -111,12 +111,61 @@ type OperationQuery struct {
Pagination pagination.Pagination
TxHash string
Address string
ChainID *vaa.ChainID
SourceChainID *vaa.ChainID
TargetChainID *vaa.ChainID
AppID string
ExclusiveAppId bool
PayloadType *float64
}
func buildQueryOperationsByChain(sourceChainID, targetChainID *vaa.ChainID, strict bool) bson.D {
var allMatch bson.A
if sourceChainID != nil {
matchSourceChain := bson.D{{Key: "$or", Value: bson.A{
bson.D{{Key: "rawStandardizedProperties.fromChain", Value: bson.M{"$eq": sourceChainID}}},
bson.D{{Key: "standardizedProperties.fromChain", Value: bson.M{"$eq": sourceChainID}}},
}}}
allMatch = append(allMatch, matchSourceChain)
}
if targetChainID != nil {
matchTargetChain := bson.D{{Key: "$or", Value: bson.A{
bson.D{{Key: "parsedPayload.toChain", Value: bson.M{"$eq": targetChainID}}},
bson.D{{Key: "parsedPayload.targetChainId", Value: bson.M{"$eq": targetChainID}}},
bson.D{{Key: "standardizedProperties.toChain", Value: bson.M{"$eq": targetChainID}}},
bson.D{{Key: "rawStandardizedProperties.toChain", Value: bson.M{"$eq": targetChainID}}},
}}}
allMatch = append(allMatch, matchTargetChain)
}
var matchParsedVaa bson.D
if strict {
matchParsedVaa = bson.D{{Key: "$match", Value: bson.D{{Key: "$and", Value: allMatch}}}}
} else {
matchParsedVaa = bson.D{{Key: "$match", Value: bson.D{{Key: "$or", Value: allMatch}}}}
}
return matchParsedVaa
}
func buildQueryOperationsByAppID(appID string, exclusive bool) bson.D {
if appID == "" {
return bson.D{{Key: "$match", Value: bson.M{}}}
}
var appIdsCondition interface{}
if exclusive {
appIdsCondition = bson.M{"$eq": []string{appID}}
} else {
appIdsCondition = bson.M{"$in": []string{appID}}
}
matchParsedVaa := bson.D{{Key: "$match", Value: bson.D{{Key: "$or", Value: bson.A{
bson.D{{Key: "appIds", Value: appIdsCondition}},
bson.D{{Key: "rawStandardizedProperties.appIds", Value: appIdsCondition}},
bson.D{{Key: "standardizedProperties.appIds", Value: appIdsCondition}},
}}}}}
return matchParsedVaa
}
// strict flag is to force that both source and target chain id must match
@ -199,7 +248,7 @@ func findOperationsIdByChain(ctx context.Context, db *mongo.Database, chainId va
}
return ids, nil
}
*/
func findOperationsIdByAppID(ctx context.Context, db *mongo.Database, appID string, exclusive bool) ([]string, error) {
@ -232,6 +281,7 @@ func findOperationsIdByAppID(ctx context.Context, db *mongo.Database, appID stri
}
return ids, nil
}
*/
// findOperationsIdByAddress returns all operations filtered by address.
func findOperationsIdByAddress(ctx context.Context, db *mongo.Database, address string, pagination *pagination.Pagination) ([]string, error) {
@ -307,6 +357,35 @@ func (r *Repository) matchOperationByTxHash(ctx context.Context, txHash string)
}}}}}
}
func (r *Repository) findOpsIdByChainAndAppId(ctx context.Context, query OperationQuery) ([]string, error) {
var pipeline mongo.Pipeline
if query.SourceChainID != nil || query.TargetChainID != nil {
matchBySourceTargetChain := buildQueryOperationsByChain(query.SourceChainID, query.TargetChainID, true)
pipeline = append(pipeline, matchBySourceTargetChain)
}
if len(query.AppID) > 0 {
matchByAppId := buildQueryOperationsByAppID(query.AppID, query.ExclusiveAppId)
pipeline = append(pipeline, matchByAppId)
}
cur, err := r.db.Collection("parsedVaa").Aggregate(ctx, pipeline)
if err != nil {
return nil, err
}
var documents []mongoID
err = cur.All(ctx, &documents)
if err != nil {
return nil, err
}
var ids []string
for _, doc := range documents {
ids = append(ids, doc.Id)
}
return ids, nil
}
// FindAll returns all operations filtered by q.
func (r *Repository) FindAll(ctx context.Context, query OperationQuery) ([]*OperationDto, error) {
@ -333,26 +412,9 @@ func (r *Repository) FindAll(ctx context.Context, query OperationQuery) ([]*Oper
// match operation by txHash (source tx and destination tx)
matchByTxHash := r.matchOperationByTxHash(ctx, query.TxHash)
pipeline = append(pipeline, matchByTxHash)
} else if query.ChainID != nil {
ids, err := findOperationsIdByChain(ctx, r.db, query.ChainID, query.ChainID, false)
if err != nil {
return nil, err
}
if len(ids) == 0 {
return []*OperationDto{}, nil
}
pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.D{{Key: "_id", Value: bson.D{{Key: "$in", Value: ids}}}}}})
} else if query.SourceChainID != nil || query.TargetChainID != nil {
ids, err := findOperationsIdByChain(ctx, r.db, query.SourceChainID, query.TargetChainID, true)
if err != nil {
return nil, err
}
if len(ids) == 0 {
return []*OperationDto{}, nil
}
pipeline = append(pipeline, bson.D{{Key: "$match", Value: bson.D{{Key: "_id", Value: bson.D{{Key: "$in", Value: ids}}}}}})
} else if len(query.AppID) > 0 {
ids, err := findOperationsIdByAppID(ctx, r.db, query.AppID, query.ExclusiveAppId)
} else if query.SourceChainID != nil || query.TargetChainID != nil || query.AppID != "" {
// find all ids that match by source and target chain id
ids, err := r.findOpsIdByChainAndAppId(ctx, query)
if err != nil {
return nil, err
}

View File

@ -34,13 +34,11 @@ func (s *Service) FindById(ctx context.Context, chainID vaa.ChainID,
type OperationFilter struct {
TxHash *types.TxHash
Address string
ChainID *vaa.ChainID
SourceChainID *vaa.ChainID
TargetChainID *vaa.ChainID
AppID string
ExclusiveAppId bool
Pagination pagination.Pagination
PayloadType *float64
}
// FindAll returns all operations filtered by q.
@ -54,12 +52,10 @@ func (s *Service) FindAll(ctx context.Context, filter OperationFilter) ([]*Opera
TxHash: txHash,
Address: filter.Address,
Pagination: filter.Pagination,
ChainID: filter.ChainID,
SourceChainID: filter.SourceChainID,
TargetChainID: filter.TargetChainID,
AppID: filter.AppID,
ExclusiveAppId: filter.ExclusiveAppId,
PayloadType: filter.PayloadType,
}
operations, err := s.repo.FindAll(ctx, operationQuery)

View File

@ -299,24 +299,6 @@ func ExtractExclusiveAppId(c *fiber.Ctx, l *zap.Logger) (bool, error) {
return strconv.ParseBool(query)
}
func ExtractPayloadType(c *fiber.Ctx, l *zap.Logger) (*float64, error) {
payloadTypeParam := c.Query("payloadType")
if payloadTypeParam == "" {
return nil, nil
}
payloadType, err := strconv.ParseFloat(payloadTypeParam, 64)
if err != nil {
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
l.Error("failed to parse payload type parameter",
zap.Error(err),
zap.String("requestID", requestID),
)
return nil, response.NewInvalidParamError(c, "INVALID PAYLOAD TYPE", errors.WithStack(err))
}
return &payloadType, nil
}
func ExtractTimeSpan(c *fiber.Ctx, l *zap.Logger) (string, error) {
// get the timeSpan from query params
timeSpanStr := c.Query("timeSpan", "1d")

View File

@ -54,17 +54,19 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error {
return err
}
chainID, err := middleware.ExtractChain(ctx, c.logger)
searchByAddress := address != ""
searchByTxHash := txHash != nil && txHash.String() != ""
if searchByAddress && searchByTxHash {
return response.NewInvalidParamError(ctx, "address and txHash cannot be used at the same time", nil)
}
sourceChain, err := middleware.ExtractSourceChain(ctx, c.logger)
if err != nil {
return err
}
sourceChainID, err := middleware.ExtractSourceChain(ctx, c.logger)
if err != nil {
return err
}
targeChainID, err := middleware.ExtractTargetChain(ctx, c.logger)
targetChain, err := middleware.ExtractTargetChain(ctx, c.logger)
if err != nil {
return err
}
@ -75,39 +77,21 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error {
return err
}
payloadType, err := middleware.ExtractPayloadType(ctx, c.logger)
if err != nil {
return err
}
searchBySourceTargetChain := sourceChain != nil || targetChain != nil
searchByAppId := appID != ""
searchByAddress := address != ""
searchByTxHash := txHash != nil && txHash.String() != ""
searchByChainId := chainID != nil
searchBySourceAndTargetChain := sourceChainID != nil && targeChainID != nil
searchByAppID := len(appID) > 0
searchByPayloadType := payloadType != nil
searchCriteria := []bool{searchByAddress, searchByTxHash, searchByChainId, searchByAppID, searchByPayloadType, searchBySourceAndTargetChain}
searchCriteriaCount := 0
for _, sc := range searchCriteria {
if sc {
searchCriteriaCount++
}
}
if searchCriteriaCount > 1 {
return response.NewInvalidParamError(ctx, "only one search-criteria can be used at once", nil)
if (searchByAddress || searchByTxHash) && (searchBySourceTargetChain || searchByAppId) {
return response.NewInvalidParamError(ctx, "address/txHash cannot be combined with sourceChain/targetChain/appId query filter", nil)
}
filter := operations.OperationFilter{
TxHash: txHash,
Address: address,
ChainID: chainID,
SourceChainID: sourceChainID,
TargetChainID: targeChainID,
SourceChainID: sourceChain,
TargetChainID: targetChain,
AppID: appID,
ExclusiveAppId: exclusiveAppId,
Pagination: *pagination,
PayloadType: payloadType,
}
// Find operations by q search param.