Skip to main content

Create a custom resolver for search

In this section, you'll write an Atlas function. Atlas functions execute JavaScript code in the cloud. The function will aggregate documents with the $search stage. Then, you'll link the function to your GraphQL API to create a custom resolver for searching players. You'll use the resolver to send search queries.

query {
searchPlayers(input: {
query: "S*ny",
operator: "wildcard",
path: "short_name",
limit: 5
}) {
long_name
club_name
player_positions
age
}
}

In the next section, you'll use the GraphQL API and the custom resolver to perform full-text search from a web application.

Implement the Atlas function

  1. Navigate to Functions on the left side menu and click Create New Function.

  2. Name it search and click Function Editor.

    The Atlas function configuration page
  3. Select everything in the text editor and replace it with the following code.

    exports = async (input) => {
    if (!input) {
    return [];
    }

    const { query, operator, path, fuzzy_max_edits, limit } = input;

    const searchStage = constructSearchStage({ query, operator, path, fuzzy_max_edits });
    const limitStage = constructLimitStage({ limit });

    const pipeline = [
    searchStage,
    limitStage,
    ].filter(stage => !!stage);

    const players = context.services.get("mongodb-atlas").db("soccer").collection("players");
    const results = await players.aggregate(pipeline).toArray();

    return results;
    };

    function constructSearchStage({ operator, query, path, fuzzy_max_edits }) {
    if (typeof operator === "string" && typeof query === "string" && typeof path === "string") {
    const searchStage = {
    "$search": {
    [operator]: {
    query,
    path
    }
    }
    };

    if (operator === "text" && typeof fuzzy_max_edits === "number") {
    searchStage.$search[operator].fuzzy = { maxEdits: fuzzy_max_edits };
    }

    if (operator == "wildcard") {
    searchStage.$search[operator].allowAnalyzedField = true;
    }

    return searchStage;
    }
    }

    function constructLimitStage({ limit }) {
    if (typeof limit === "number") {
    return {
    $limit: limit
    };
    }
    }
  4. Click Save Draft.

  5. Click Review Draft & Deploy on the blue banner, scroll to the bottom and click Deploy.

Connect the function to the GraphQL API

Next, you'll connect the search function to the GraphQL API. The function will be a custom resolver allowing you to send queries that search for players.

  1. Navigate to GraphQL on the left side menu and then, click the Custom Resolvers tab.

    The GraphQL page in Atlas with the 'Custom Resolvers' tab highlighted
  2. Click Add a Custom Resolver and use the following configuration:

    • GraphQL Field Name: searchPlayers

    • Parent Type: Query

    • Function: search

    • Input Type: Custom Type

      • Add the following JSON schema for the input type:
        {
        "type": "object",
        "title": "SearchQueryInput",
        "properties": {
        "query": {
        "type": "string"
        },
        "operator": {
        "type": "string"
        },
        "path": {
        "type": "string"
        },
        "fuzzy_max_edits": {
        "type": "number"
        },
        "limit": {
        "type": "number"
        }
        }
        }
    • Payload Type

      • Existing Type (List)
      • [Player]
  3. Click Save Changes.

Query the custom resolver

  1. Navigate back to the GraphQL tab on the side menu.

  2. Enter the following query into the GraphiQL editor and click the execute button.

    query {
    searchPlayers(input: {
    query: "S*ny",
    operator: "wildcard",
    path: "short_name",
    limit: 5
    }) {
    long_name
    club_name
    player_positions
    age
    }
    }
  3. You should see two players returned in the response.

    {
    "data": {
    "searchPlayers": [
    {
    "age": 31,
    "club_name": "Juventus",
    "long_name": "Wojciech Tomasz Szczęsny",
    "player_positions": "GK"
    },
    {
    "age": 27,
    "club_name": "SC Paderborn 07",
    "long_name": "Dennis Srbeny",
    "player_positions": "ST"
    }
    ]
    }
    }

Great job! Feel free to modify the query and play with the resolver!