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
Navigate to Functions on the left side menu and click Create New Function.
Name it
search
and click Function Editor.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
};
}
}Click Save Draft.
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.
Navigate to GraphQL on the left side menu and then, click the Custom Resolvers tab.
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"
}
}
}
- Add the following JSON schema for the input type:
Payload Type
- Existing Type (List)
- [Player]
Click Save Changes.
Query the custom resolver
Navigate back to the GraphQL tab on the side menu.
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
}
}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!