graphql-compose / graphql-compose-elasticsearch

Hide Elastic Search REST API behind GraphQL.

Home Page:https://graphql-compose.herokuapp.com/elasticsearch/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

autosuggest query for elastic

amarflybot18 opened this issue · comments

Hi @nodkz , Do you have support for autosuggest query?

Nope, I didn't find a general solution.

So I recommend creating suggest resolver manually. Something like this:

export const addSuggestR = <TSource, TContext>(
  TC: ObjectTypeComposer<TSource, TContext>
): ObjectTypeComposer<TSource, TContext> => {
  return TC.addResolver({
    name: 'suggest',
    kind: 'query',
    type: [
      TC.schemaComposer.createObjectTC({
        name: `${TC.getTypeName()}SuggestType`,
        fields: {
          _id: 'String',
          score: 'Float',
          ...TC.getFields(),
        },
      }),
    ],
    args: {
      q: 'String',
      limit: 'Int',
      popular: 'Boolean',
    },
    resolve: async ({ args }) => {
      const { q, limit, popular } = args || {};
      const suggestBody = {
        query: {
          bool: {
            should: [
              // match regular title
              {
                match: {
                  title: {
                    query: q,
                    boost: 6,
                    fuzziness: 'auto',
                  },
                },
              },
              // match inverse_keyboard title
              {
                match: {
                  title: {
                    query: q,
                    analyzer: 'search_analyzer_inverse_keyboard',
                    boost: 5,
                    fuzziness: 'auto',
                  },
                },
              },
              // match regular _all
              {
                match: {
                  _all: {
                    query: q,
                    boost: 4,
                    fuzziness: 'auto',
                  },
                },
              },
              // match inverse_keyboard _all
              {
                match: {
                  _all: {
                    query: q,
                    analyzer: 'search_analyzer_inverse_keyboard',
                    boost: 3,
                    fuzziness: 'auto',
                  },
                },
              },
              // match regular synonyms
              {
                match: {
                  synonyms: {
                    query: q,
                    boost: 2,
                    fuzziness: 'auto',
                  },
                },
              },
              // match inverse_keyboard synonyms
              {
                match: {
                  synonyms: {
                    query: q,
                    analyzer: 'search_analyzer_inverse_keyboard',
                    fuzziness: 'auto',
                  },
                },
              },
            ],
            minimum_should_match: 1,
          },
        },
        _source: true,
        size: limit || 10,
      };

      const suggestPopularBody = {
        query: {
          range: {
            popular: {
              gt: 0,
            },
          },
        },
        sort: [{ popular: { order: 'desc' } }],
        _source: true,
        size: limit || 10,
      };

      const res = await elasticClient.search({
        index: 'dic',
        type: generateESType(TC.getTypeName()), // Model.modelName
        body: popular ? suggestPopularBody : suggestBody,
      });

      if (res?.hits?.hits?.length > 0)
        return res.hits.hits.map(item => {
          return {
            _id: item._id,
            score: item._score,
            ...item._source,
          };
        });

      return [];
    },
  });
};

Thanks a lot.