diff --git a/graphql/resolver/queries/characters.go b/graphql/resolver/queries/characters.go index b6d994a..0305be4 100644 --- a/graphql/resolver/queries/characters.go +++ b/graphql/resolver/queries/characters.go @@ -2,52 +2,57 @@ package queries import ( "context" - "errors" - "git.aiterp.net/rpdata/api/graphql/loader" "git.aiterp.net/rpdata/api/graphql/resolver/types" "git.aiterp.net/rpdata/api/model/character" ) // CharactersArgs is args for characters query type CharactersArgs struct { - IDs *[]string - Nicks *[]string - Author *string + Filter *struct { + IDs *[]string + Nicks *[]string + Names *[]string + Author *string + Search *string + } } // Characters resolves the characters query func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*types.CharacterResolver, error) { - var chars []character.Character + var characters []character.Character var err error - loader := loader.FromContext(ctx) - if loader == nil { - return nil, errors.New("no loader") - } + filter := args.Filter + if filter != nil { + var ids []string + var nicks []string + var names []string - switch { - case args.IDs != nil: - chars, err = character.ListIDs(*args.IDs...) - case args.Nicks != nil: - chars, err = character.ListNicks(*args.Nicks...) - case args.Author != nil: - chars, err = character.ListAuthor(*args.Author) - default: - chars, err = character.List() - } - - if err != nil { - return nil, err - } + if filter.IDs != nil { + ids = *filter.IDs + } + if filter.Nicks != nil { + nicks = *filter.Nicks + } + if filter.Names != nil { + names = *filter.Names + } - resolvers := make([]*types.CharacterResolver, 0, len(chars)) - for i := range chars { - if chars[i].ID == "" { - continue + characters, err = character.ListFilter(ids, nicks, names, filter.Author, filter.Search) + if err != nil { + return nil, err } + } else { + characters, err = character.List() + if err != nil { + return nil, err + } + } - resolvers = append(resolvers, &types.CharacterResolver{C: chars[i]}) + resolvers := make([]*types.CharacterResolver, 0, len(characters)) + for _, character := range characters { + resolvers = append(resolvers, &types.CharacterResolver{C: character}) } return resolvers, nil diff --git a/graphql/schema/root.graphql b/graphql/schema/root.graphql index fdb4486..0ed2761 100644 --- a/graphql/schema/root.graphql +++ b/graphql/schema/root.graphql @@ -3,8 +3,8 @@ type Query { # Find character by either an ID or a nick. character(id: String, nick: String): Character - # Find characters by either a list of ids, nicks or an author. Only one parameter at a time - characters(ids: [String!], nicks: [String!], author: String): [Character!]! + # Find characters + characters(filter: CharactersFilter): [Character!]! # Find channel by name @@ -32,7 +32,7 @@ type Query { # Find file by ID file(id: String!): File - # Files get all available files. If includePublic is set, it will return public files as well + # Find files files(filter: FilesFilter): [File!]! diff --git a/graphql/schema/types/character.graphql b/graphql/schema/types/character.graphql index 47cc5f5..a35918e 100644 --- a/graphql/schema/types/character.graphql +++ b/graphql/schema/types/character.graphql @@ -22,6 +22,24 @@ type Character { description: String! } +# Filter for characters query +input CharactersFilter { + # Filter by character IDs + ids: [String!] + + # Filter by nicks + nicks: [String!] + + # Filter by names + names: [String!] + + # Filter by author + author: String + + # Filter by text search matching against the character's description + search: String +} + # Input for adding characters input CharacterAddInput { # The primary IRC nick name to recognize this character by diff --git a/model/character/character.go b/model/character/character.go index e342286..6f7e4c6 100644 --- a/model/character/character.go +++ b/model/character/character.go @@ -154,6 +154,29 @@ func ListIDs(ids ...string) ([]Character, error) { return list(bson.M{"_id": bson.M{"$in": ids}}) } +// ListFilter lists all logs matching the filters. +func ListFilter(ids []string, nicks []string, names []string, author *string, search *string) ([]Character, error) { + query := bson.M{} + + if len(ids) > 0 { + query["_id"] = bson.M{"$in": ids} + } + if len(nicks) > 0 { + query["nicks"] = bson.M{"$in": nicks} + } + if len(names) > 0 { + query["name"] = bson.M{"$in": names} + } + if author != nil { + query["author"] = *author + } + if search != nil { + query["$text"] = bson.M{"$search": *search} + } + + return list(query) +} + // New creates a Character and pushes it to the database. It does some validation // on nick, name, shortName and author. Leave the shortname blank to have it be the // first name. @@ -227,5 +250,11 @@ func init() { if err != nil { log.Fatalln("init common.characters:", err) } + err = collection.EnsureIndex(mgo.Index{ + Key: []string{"$text:description"}, + }) + if err != nil { + log.Fatalln("init common.characters:", err) + } }) }