Search code examples
c#.netgraphqlhotchocolate

How to organize unified search by multiply types (C#/HotChocolate)


I want to implement a unified search in my app - a single endpoint that returns results of different types by some search token. My current realization is straightforward.

HotChocolate query:

    [ExtendObjectType("Query")]
    public class SearchQueries
    {
        [UseDbContext(typeof(ApplicationDbContext))]
        public async Task<SearchResult> GetSearch(
            [Argument("token")] string token,
            [ScopedService] ApplicationDbContext dbContext,
            CancellationToken cancellationToken)
        {
            var users = await dbContext.Users
                .Where(s => s.Name.Contains(token))
                .ToArrayAsync(cancellationToken);
            
            var services = await dbContext.Services
                .Where(s => s.Name.Contains(token))
                .ToArrayAsync(cancellationToken);
            
            return new SearchResult
            {
                Users = users,
                Services = services
            };
        }
    }

GrahpQL query:

query Search($token: String!){
  search(token: $token) {
    services {
      name
    },
    users {
      name,
      about
    }
  }
}

GrahpQL response

{
  "data": {
    "search": {
      "services": [
        {
          "name": "Test service 1"
        },
        {
          "name": "Test service 2"
        },
        {
          "name": "Test service 3"
        }
      ],
      "researchers": [
        {
          "name": "User 1",
          "about": "About user 1"
        },
        {
          "name": "User 2",
          "about": "About user 2"
        }
      ]
    }
  }
}

But I want to do it more robust: without intermediate type SearchResult, with Global Object Identification. Is there any other way to do so?

Should I do it just like that?:

query Search($token: String!){
    services(token: $token) {
      nodes {
        name
      }
    },
    researchers(token: $token) {
      nodes {
        name,
        about
      }
    }
}

Solution

  • As far as I understand your question, it is very easy to achieve. In your query type for each entity type define the method with "token" parameter which will return the filtered collection. Having that, make the queries as you have already proposed:

    query Search($token: String!){
    services(token: $token) {
      nodes {
        name
      }
    },
    researchers(token: $token) {
      nodes {
        name,
        about
      }
    }
    

    }