actual zone search support? owo

This commit is contained in:
Emi Matchu 2020-09-01 20:06:54 -07:00
parent 821d05c141
commit a11ff1326b
4 changed files with 116 additions and 9 deletions

View file

@ -204,6 +204,21 @@ function useSearchResults(query, outfitState) {
setIsEndOfResults(false);
}, [query]);
// NOTE: This query should always load ~instantly, from the client cache.
const { data: zoneData } = useQuery(gql`
query SearchPanelZones {
allZones {
id
label
}
}
`);
const allZones = zoneData?.allZones || [];
const filterToZones = query.filterToZoneLabel
? allZones.filter((z) => z.label === query.filterToZoneLabel)
: [];
const filterToZoneIds = filterToZones.map((z) => z.id);
// Here's the actual GQL query! At the bottom we have more config than usual!
const {
loading: loadingGQL,
@ -215,11 +230,13 @@ function useSearchResults(query, outfitState) {
query SearchPanel(
$query: String!
$speciesId: ID!
$zoneIds: [ID!]!
$colorId: ID!
$offset: Int!
) {
itemSearchToFit(
query: $query
zoneIds: $zoneIds
speciesId: $speciesId
colorId: $colorId
offset: $offset
@ -257,7 +274,13 @@ function useSearchResults(query, outfitState) {
${itemAppearanceFragment}
`,
{
variables: { query: debouncedQuery.value, speciesId, colorId, offset: 0 },
variables: {
query: debouncedQuery.value,
zoneIds: filterToZoneIds,
speciesId,
colorId,
offset: 0,
},
skip: !debouncedQuery.value && !debouncedQuery.filterToZoneLabel,
notifyOnNetworkStatusChange: true,
onCompleted: (d) => {

View file

@ -233,6 +233,7 @@ const typeDefs = gql`
query: String!
speciesId: ID!
colorId: ID!
zoneIds: [ID!]
offset: Int
limit: Int
): ItemSearchResult!
@ -634,7 +635,7 @@ const resolvers = {
},
itemSearchToFit: async (
_,
{ query, speciesId, colorId, offset, limit },
{ query, speciesId, colorId, zoneIds, offset, limit },
{ petTypeBySpeciesAndColorLoader, itemSearchToFitLoader }
) => {
const petType = await petTypeBySpeciesAndColorLoader.load({
@ -645,6 +646,7 @@ const resolvers = {
const items = await itemSearchToFitLoader.load({
query: query.trim(),
bodyId,
zoneIds,
offset,
limit,
});

View file

@ -189,7 +189,7 @@ const buildItemSearchToFitLoader = (db, loaders) =>
// This isn't actually optimized as a batch query, we're just using a
// DataLoader API consistency with our other loaders!
const queryPromises = queryAndBodyIdPairs.map(
async ({ query, bodyId, offset, limit }) => {
async ({ query, bodyId, zoneIds = [], offset, limit }) => {
const actualOffset = offset || 0;
const actualLimit = Math.min(limit || 30, 30);
@ -200,6 +200,10 @@ const buildItemSearchToFitLoader = (db, loaders) =>
const matcherPlaceholders = words
.map((_) => "t.name LIKE ?")
.join(" AND ");
const zoneIdsPlaceholder =
zoneIds.length > 0
? `swf_assets.zone_id IN (${zoneIds.map((_) => "?").join(", ")})`
: "1";
const [rows, _] = await db.execute(
`SELECT DISTINCT items.*, t.name FROM items
INNER JOIN item_translations t ON t.item_id = items.id
@ -207,10 +211,17 @@ const buildItemSearchToFitLoader = (db, loaders) =>
ON rel.parent_type = "Item" AND rel.parent_id = items.id
INNER JOIN swf_assets ON rel.swf_asset_id = swf_assets.id
WHERE ${matcherPlaceholders} AND t.locale="en" AND
(swf_assets.body_id = ? OR swf_assets.body_id = 0)
(swf_assets.body_id = ? OR swf_assets.body_id = 0) AND
${zoneIdsPlaceholder}
ORDER BY t.name
LIMIT ? OFFSET ?`,
[...wordMatchersForMysql, bodyId, actualLimit, actualOffset]
[
...wordMatchersForMysql,
bodyId,
...zoneIds,
actualLimit,
actualOffset,
]
);
const entities = rows.map(normalizeRow);

View file

@ -119,7 +119,8 @@ describe("ItemSearch", () => {
ON rel.parent_type = \\"Item\\" AND rel.parent_id = items.id
INNER JOIN swf_assets ON rel.swf_asset_id = swf_assets.id
WHERE t.name LIKE ? AND t.name LIKE ? AND t.locale=\\"en\\" AND
(swf_assets.body_id = ? OR swf_assets.body_id = 0)
(swf_assets.body_id = ? OR swf_assets.body_id = 0) AND
1
ORDER BY t.name
LIMIT ? OFFSET ?",
Array [
@ -134,6 +135,73 @@ describe("ItemSearch", () => {
`);
});
it("loads Neopian Times items that fit the Starry Zafara as a Background", async () => {
const res = await query({
query: gql`
query {
itemSearchToFit(
query: "Neopian Times"
speciesId: "54"
colorId: "75"
zoneIds: ["3"]
) {
query
items {
id
name
}
}
}
`,
});
expect(res).toHaveNoErrors();
expect(res.data).toMatchInlineSnapshot(`
Object {
"itemSearchToFit": Object {
"items": Array [
Object {
"id": "40431",
"name": "Neopian Times Background",
},
],
"query": "Neopian Times",
},
}
`);
expect(getDbCalls()).toMatchInlineSnapshot(`
Array [
Array [
"SELECT * FROM pet_types WHERE (species_id = ? AND color_id = ?)",
Array [
"54",
"75",
],
],
Array [
"SELECT DISTINCT items.*, t.name FROM items
INNER JOIN item_translations t ON t.item_id = items.id
INNER JOIN parents_swf_assets rel
ON rel.parent_type = \\"Item\\" AND rel.parent_id = items.id
INNER JOIN swf_assets ON rel.swf_asset_id = swf_assets.id
WHERE t.name LIKE ? AND t.name LIKE ? AND t.locale=\\"en\\" AND
(swf_assets.body_id = ? OR swf_assets.body_id = 0) AND
swf_assets.zone_id IN (?)
ORDER BY t.name
LIMIT ? OFFSET ?",
Array [
"%Neopian%",
"%Times%",
"180",
"3",
30,
0,
],
],
]
`);
});
it("searches for each word separately (fit mode)", async () => {
const res = await query({
query: gql`
@ -183,7 +251,8 @@ describe("ItemSearch", () => {
ON rel.parent_type = \\"Item\\" AND rel.parent_id = items.id
INNER JOIN swf_assets ON rel.swf_asset_id = swf_assets.id
WHERE t.name LIKE ? AND t.name LIKE ? AND t.locale=\\"en\\" AND
(swf_assets.body_id = ? OR swf_assets.body_id = 0)
(swf_assets.body_id = ? OR swf_assets.body_id = 0) AND
1
ORDER BY t.name
LIMIT ? OFFSET ?",
Array [
@ -242,7 +311,8 @@ describe("ItemSearch", () => {
ON rel.parent_type = \\"Item\\" AND rel.parent_id = items.id
INNER JOIN swf_assets ON rel.swf_asset_id = swf_assets.id
WHERE t.name LIKE ? AND t.locale=\\"en\\" AND
(swf_assets.body_id = ? OR swf_assets.body_id = 0)
(swf_assets.body_id = ? OR swf_assets.body_id = 0) AND
1
ORDER BY t.name
LIMIT ? OFFSET ?",
Array [
@ -324,7 +394,8 @@ describe("ItemSearch", () => {
ON rel.parent_type = \\"Item\\" AND rel.parent_id = items.id
INNER JOIN swf_assets ON rel.swf_asset_id = swf_assets.id
WHERE t.name LIKE ? AND t.locale=\\"en\\" AND
(swf_assets.body_id = ? OR swf_assets.body_id = 0)
(swf_assets.body_id = ? OR swf_assets.body_id = 0) AND
1
ORDER BY t.name
LIMIT ? OFFSET ?",
Array [