Bonjour à tous,

Je développe pour m'excercer une petit API pour un CMS.

J'utilise expressjs et mongoose.

J'ai une collection d'articles et j'aimerai bien pouvoir appliquer plusieurs filtres dessus mais je ne vois pas comment faire cela de la meilleur des manières.

par exemple lorsque j'appelle mon api via la route: /api/posts?publicationDateFrom=17-01-09&publicationDateTo=18-01-09&sort=title,asc

Pour le moment je ne fais que trier avec la méthode sort de mongoose.

Dans mon controller posts cela donne :

class PostsController{

    getAllPosts(){
        return async (req, res, next) => {
            const page = req.query.page || 0;
            const size = req.query.size || 2
            if(req.query.sort){
                const results = await this.sortPosts(req.query.sort);

                res.json(results);
            }else{
                const results = await Post.find({})
                    .sort({created : -1})
                    .populate('tags')
                    .limit(size)
                    .skip(page * size)

                res.json(results);
            }   
        }
    }

    async sortPosts(sort){
        var sortArray = sort.split(',');
        var sortField = sortArray[0];
        var sortValue = sortArray[1];
        var results
        switch (sortField){
            case 'title' : 
                results = await Post.find({}).sort({title : sortValue}).populate('tags');
                break;

            case 'author' : 
                results = await Post.find({}).sort({author : sortValue}).populate('tags');
                break;

            case 'creationDate' : 
                results = await Post.find({}).sort({created : sortValue}).populate('tags');
                break;

            default:
            results = await Post.find({}).populate('tags');
        }
        return results;
    }
}

....

Mais honnetement je doute que ce soit la meilleure des manières de faire.

Et ensuite comment faire pour générer une reqûete a partir des paramètres que j'ai passé a ma route?
Je ne veux pas commencer à faire mille conditions.

Si vous avez une piste sur laquelle me lancer ce serait top :)

Merci d'avance !

2 réponses


Salut,

Je ne trouve pas ça déconnent, au contraire. Ca manque un chouïa d'optimisation. Tu pourrais utiliser la syntaxe ES2015 par exemple. Sinon rien à redire. Après chacun a sa propre façon de faire y'en a pas fe "meilleure" on va dire.

Hello betaWeb,

J'ai finalement trouvé une solution à mon problème.

J'ai créer une custom query via une méthode statique de mon schema Post.

Je met le code si jamais ça interesse quelqu'un :)

const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate');
const Schema = mongoose.Schema;

const postSchema = new Schema({
    title : String,
    author : String,
    body : String,
    created : {type : Date, default: Date.now},
    publish : Boolean,
    tags: [{type : Schema.Types.ObjectId, ref : 'Tag' }]
});

postSchema.plugin(mongoosePaginate);

postSchema.statics = {

    search : async function(params){
        const author = params.author;
        const title = params.title;
        const createdAt = params.createdAt;
        const publish = params.publish;
        const tag = params.tag;
        const currentPage = params.page || 1;
        var currentLimit = params.limit || 5;

        let query = this.find()

        if(author){
            query.where('author', author)
        }

        if(title){
            query.where('title', title)
        }

        if(createdAt){
            query.where('created', createdAt)
        }

        if(publish){
            query.where('publish', publish)
        }

        if(tag){
            query.where('tags').ne([]).populate({
                path : 'tags',
                match : {
                    tagName : tag
                }
            })

        }else{
            query.populate('tags')
        }

        // const results = await mongoosePaginate.paginate.call(this, query, {page : currentPage, limit : parseInt(currentLimit)});
        const results = await query.exec();

        return results

    }

}

const Post = mongoose.model('Post', postSchema);

module.exports = Post;

Je dois encore rajouter ma conditions sur le triage (sort) que j'avais fait dans mon controller.

Par contre j'ai un autre petit soucis, lorsque je fais une recherche spéciale sur une ref externe.

Par exemple ici, ma clé Tag dans mon postSchema est lié à mon tagSchema pour pouvoir populate() dessus.

Lorsque je fais une requête du style api?tag=Vacances

Il va bien me sortir les posts qui ne contiennet que le tag "Vacances" mais par contre si je fais api?tag=tagQuiNexistepas

(Ce tag n'existe pas dans ma db et n'est donc lié à aucuns posts)

Cela va quand même me sortir juste mes posts avec le tag Vacances car dans ma reqûetes je fais query.where('tags').ne([])

Mais je ne comprends pas pourquoi il me sort les posts avec le tag Vacances car je fais aussi un filtre sur mon populate

 .populate({
                path : 'tags',
                match : {
                    tagName : tag
                }
            })

Une idée de comment fixer ça?

Merci d'avance =)