skip to Main Content

I have an online game store and code that filters data by tags and genres. But I also want to add filtering by platforms and systems. For example, the system is PC and the platform is Steam. How can I implement this?

Schema

const mongoose = require("mongoose");
const slug = require('mongoose-slug-updater');
const options = {
    separator: "-",
    lang: "en",
    truncate: 120
}
mongoose.plugin(slug, options);
const GamesSchema = new mongoose.Schema({
    title: String,
    slug: { type: String, slug: ["title"], slugPaddingSize: 2, unique: true },
    last_url: String,
    description: String,
    preview: {
        src: String,
        alt: String
    },
    stock_price: String,
    discount: Number,
    total_price: String,
    system: Array,
    platform: String,
    info: {
        Genre: Array
    },
    tags: Array,
    config: Object,
    images: Array,
    keys: Array,
    content: String
})
module.exports = mongoose.model("Games", GamesSchema);

api controller

async get(req, res) {
        try {
            const page = parseInt(req.query.page) - 1 || 0;
            const limit = parseInt(req.query.limit) || 5;
            const search = req.query.search || '';
            let sort = req.query.sort || "top";
            let tags = req.query.tags || 'all';
            const tagsOpt = [];
            Games.find().then(async games => {
                games.forEach(game => {
                    game.tags.forEach(tag => {
                        if (!tagsOpt.includes(tag)) {
                            tagsOpt.push(tag)
                        }
                    })
                })

                tags === 'all' ? (tags = [...tagsOpt]) : (tags = req.query.tags.split(','));
                req.query.sort ? (sort = req.query.sort.split(',')) : (sort = [sort]);

                let sortBy = {};
                if (sort[1]) {
                    sortBy[sort[0] = sort[1]];
                } else {
                    sortBy[sort[0] = "top"]
                }
                const gamesData = await Games.find({ title: { $regex: search, $options: 'i' } })
                    .where('tags')
                    .in([...tags])
                    .sort(sortBy)
                    .skip(page * limit)
                    .limit(limit);

                const total = await Games.countDocuments({
                    tags: { $in: [...tags] },
                    title: { $regex: search, $options: 'i' },
                });
                const response = {
                    error: false,
                    total,
                    page: page + 1,
                    limit,
                    tags: tagsOpt,
                    gamesData
                };
                res.status(200).json(response);
            })
        } catch (error) {
            console.log(error);
            res.status(400).json({ message: 'Ошибка получения' })
        }
    }

I was able to combine genres and tags into one and filter by them, do I really now need to put both the platform and the systems into an array of tags?

2

Answers


  1. Chosen as BEST ANSWER

    Thank you!) This solution works, but I did it a little differently, since I need the search by platforms and systems to be a multi-search, that is, I could filter simultaneously for PC, Xbox, as well as for Steam Origin platforms, etc. So I did this:

    const page = parseInt(req.query.page) - 1 || 0;
            const limit = parseInt(req.query.limit) || 5;
            const search = req.query.search || '';
            let sort = req.query.sort || "rating";
            let tags = req.query.tags || 'all';
            let system = req.query.system || 'all';
            let platform = req.query.platform || 'all';
            let language = req.query.language || 'all';
            const tagsOpt = [];
            const platformOpt = [];
            const systemOpt = [];
            const languageOpt = [];
            Games.find().then(async games => {
                games.forEach(game => {
                    game.tags.forEach(tag => {
                        if (!tagsOpt.includes(tag)) {
                            tagsOpt.push(tag)
                        }
                    })
                    if (!platformOpt.includes(game.platform)) {
                        platformOpt.push(game.platform)
                    }
                    if (!systemOpt.includes(game.system)) {
                        systemOpt.push(game.system)
                    }
                    game.languages.forEach(language => {
                        if (!languageOpt.includes(language)) {
                            languageOpt.push(language)
                        }
                    })
                })
    
                tags === 'all' ? (tags = [...tagsOpt]) : (tags = req.query.tags.split(','));
                platform === 'all' ? (platform = [...platformOpt]) : (platform = req.query.platform.split(','));
                system === 'all' ? (system = [...systemOpt]) : (system = req.query.system.split(','));
                language === 'all' ? (language = [...languageOpt]) : (language = req.query.language.split(','));
                req.query.sort ? (sort = req.query.sort.split(',')) : (sort = [sort]);
    
                let sortBy = {};
                if (sort[1]) {
                    sortBy[sort[0]] = sort[1];
                } else {
                    sortBy[sort[0]] = "asc";
                }
                const gamesData = await Games.find({ title: { $regex: search, $options: 'i' } })
                    .where('tags').in([...tags])
                    .where('platform').in([...platform])
                    .where('system').in([...system])
                    .where('languages').in([...language])
                    .sort(sortBy)
                    .skip(page * limit)
                    .limit(limit);
    
                const total = await Games.countDocuments({
                    tags: { $in: [...tags] },
                    title: { $regex: search, $options: 'i' },
                });
                const response = {
                    error: false,
                    total,
                    page: page + 1,
                    limit,
                    tags: tagsOpt,
                    language: languageOpt,
                    platform: platformOpt,
                    system: systemOpt,
                    gamesData
                };
                res.status(200).json(response);
            })
    

    Or can I optimize this?


  2. No, you don’t need to put both the platform and the systems into an array of tags. You can filter by platform and system separately.

    You can add two more query parameters for platform and system in your API and then use them in your mongoose query. Here’s how you can do it:

    async get(req, res) {
        try {
            const page = parseInt(req.query.page) - 1 || 0;
            const limit = parseInt(req.query.limit) || 5;
            const search = req.query.search || '';
            let sort = req.query.sort || "top";
            let tags = req.query.tags || 'all';
            const platform = req.query.platform || '';
            const system = req.query.system || '';
            const tagsOpt = [];
            Games.find().then(async games => {
                games.forEach(game => {
                    game.tags.forEach(tag => {
                        if (!tagsOpt.includes(tag)) {
                            tagsOpt.push(tag)
                        }
                    })
                })
    
                tags === 'all' ? (tags = [...tagsOpt]) : (tags = req.query.tags.split(','));
                req.query.sort ? (sort = req.query.sort.split(',')) : (sort = [sort]);
    
                let sortBy = {};
                if (sort[1]) {
                    sortBy[sort[0] = sort[1]];
                } else {
                    sortBy[sort[0] = "top"]
                }
                const gamesData = await Games.find({ 
                    title: { $regex: search, $options: 'i' },
                    platform: { $regex: platform, $options: 'i' },
                    system: { $in: system.split(',') }
                })
                    .where('tags')
                    .in([...tags])
                    .sort(sortBy)
                    .skip(page * limit)
                    .limit(limit);
    
                const total = await Games.countDocuments({
                    tags: { $in: [...tags] },
                    title: { $regex: search, $options: 'i' },
                    platform: { $regex: platform, $options: 'i' },
                    system: { $in: system.split(',') }
                });
                const response = {
                    error: false,
                    total,
                    page: page + 1,
                    limit,
                    tags: tagsOpt,
                    gamesData
                };
                res.status(200).json(response);
            })
        } catch (error) {
            console.log(error);
            res.status(400).json({ message: 'Ошибка получения' })
        }
    }
    

    In this code, I’ve added two new query parameters platform and system. The platform is a string and system is an array. I’ve used $regex for platform to make it case-insensitive and $in for system to match any system in the array.

    Now, you can filter games by platform and system by adding platform and system parameters in your API request like this: /api/games?platform=Steam&system=PC,Mac.

    Please replace the file path with your actual file path.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search