| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | package search | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 04:25:56 +08:00
										 |  |  | const randomSortKey string = "@random" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | // sort field directions
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	SortAsc  string = "ASC" | 
					
						
							|  |  |  | 	SortDesc string = "DESC" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SortField defines a single search sort field.
 | 
					
						
							|  |  |  | type SortField struct { | 
					
						
							|  |  |  | 	Name      string `json:"name"` | 
					
						
							|  |  |  | 	Direction string `json:"direction"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // BuildExpr resolves the sort field into a valid db sort expression.
 | 
					
						
							|  |  |  | func (s *SortField) BuildExpr(fieldResolver FieldResolver) (string, error) { | 
					
						
							| 
									
										
										
										
											2023-01-08 04:25:56 +08:00
										 |  |  | 	// special case for random sort
 | 
					
						
							|  |  |  | 	if s.Name == randomSortKey { | 
					
						
							|  |  |  | 		return "RANDOM()", nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result, err := fieldResolver.Resolve(s.Name) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// invalidate empty fields and non-column identifiers
 | 
					
						
							| 
									
										
										
										
											2023-01-08 04:25:56 +08:00
										 |  |  | 	if err != nil || len(result.Params) > 0 || result.Identifier == "" || strings.ToLower(result.Identifier) == "null" { | 
					
						
							|  |  |  | 		return "", fmt.Errorf("invalid sort field %q", s.Name) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 04:25:56 +08:00
										 |  |  | 	return fmt.Sprintf("%s %s", result.Identifier, s.Direction), nil | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseSortFromString parses the provided string expression
 | 
					
						
							|  |  |  | // into a slice of SortFields.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Example:
 | 
					
						
							| 
									
										
										
										
											2023-02-24 03:51:42 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | //	fields := search.ParseSortFromString("-name,+created")
 | 
					
						
							| 
									
										
										
										
											2022-07-13 00:52:09 +08:00
										 |  |  | func ParseSortFromString(str string) (fields []SortField) { | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 	data := strings.Split(str, ",") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, field := range data { | 
					
						
							|  |  |  | 		// trim whitespaces
 | 
					
						
							|  |  |  | 		field = strings.TrimSpace(field) | 
					
						
							|  |  |  | 		if strings.HasPrefix(field, "-") { | 
					
						
							| 
									
										
										
										
											2022-07-13 00:52:09 +08:00
										 |  |  | 			fields = append(fields, SortField{strings.TrimPrefix(field, "-"), SortDesc}) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2022-07-13 00:52:09 +08:00
										 |  |  | 			fields = append(fields, SortField{strings.TrimPrefix(field, "+"), SortAsc}) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 00:52:09 +08:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | } |