0

I want to make a params for tags and it can contain multiple tags so it must be an array.

SOLVED I check with my console, if there are only 1 tag, tags only return tag1. But if there are more than 1 tag, tags return ['tag1','tag2']. example tags

PROBLEM How to .find() using $in with array

My code for now is

async function index(req, res, next) {
    try {
        let { limit = 10, skip = 0, q = '', category = '', tags = [] } = req.query;

        let criteria = {};

        ...

        if (tags.length) {
            tags = Array.isArray(tags) ? tags : tags.split();
            console.log(tags)

            tags = await Tag.find({ name: { $in: tags } });
            criteria = { ...criteria, tags: { $in: tags.map(tag => tag._id) } }
        }

        ...
           
    }

Product model schema

const productSchema = Schema({

    ...

    // One-To-Many
    tags: [{ type: Schema.Types.ObjectId, ref: 'Tag' }]

}, { timestamps: true });

module.exports = model('Product', productSchema);

Tag model schema

const tagSchema = Schema({
    name: {
        type: String,
        minlength: [3, 'Min length is 3 character!'],
        maxlength: [20, 'Max length is 20 character!'],
        required: [true, 'Tag name must be filled!']
    }
});

module.exports = model('Tag', tagSchema)

The problem is the console return empty array and I don't know what's wrong. Any idea? example empty array

Success return example

Koh Endru
  • 13
  • 5
  • I see you may be directly hitting the find function with stingified tags Id, you may need to use mongoose.Types.ObjectId() or something to convert it to a mongoId before finding – yash kothari Aug 04 '21 at 04:56
  • Check out this https://stackoverflow.com/a/8393613/8494319 – yash kothari Aug 04 '21 at 04:57
  • 1
    @yashkothari this is my first though about the error. But it still return empty array when I use the ObjectId in tags params – Koh Endru Aug 04 '21 at 05:09

2 Answers2

1

I found the solution for it. It's just about case sensitive in mongo query Check the docs here.

Code for multiple tags with case sensitive

        if (tags.length) {
            // Split the array
            tags = Array.isArray(tags) ? tags : tags.split();
            console.log(tags)

            // Case sensitive
            var optValues = tags;
            var optRegexp = [];
            optValues.forEach(function (opt) {
                optRegexp.push(new RegExp(opt, 'i'));
            });
            console.log(optRegexp)

            tags = await Tag.find({ name: { $in: optRegexp } });
            console.log("tags found" + tags)

            criteria = { ...criteria, tags: { $in: tags.map(tag => tag._id) } }
        }

Thanks for everyone who help me, I appreciate it.

Koh Endru
  • 13
  • 5
0

Try this..

If you pass a param in Postman with a single tag then it will give you string value. More than one tags will give array. In that case make it as follows

 let { limit = 10, skip = 0, q = '', category = '', tags = [] } = req.query;
    tags = Array.isArray(tags) ? tags : tags.split();
    console.log(tags)

tags = await Tag.find({ "tags.name": { $in: tags } }); As per your document, tags array has objects. So, match query would be {"tags.name" : {$in:tags}}

 tags = await Tag.find({ "tags.name": { $in: tags } });
Selva Mary
  • 658
  • 1
  • 4
  • 17
  • This code is useful for make single tags into a array, thanks. But the problem is how to use .find() and $in using array because it returned empty array, [check](https://i.ibb.co/c2tn14V/return-empty-array.jpg). I'll updated my question @selva-mary – Koh Endru Aug 04 '21 at 04:45
  • It still return empty array. Check it with console after `tags = await Tag.find...` and the console is empty, means `.find()` didn't return correctly – Koh Endru Aug 04 '21 at 05:12
  • Answer updated with [mongoplayground](https://mongoplayground.net/p/fuSm_dUejnb) – Selva Mary Aug 04 '21 at 05:56
  • what you share is using string `"tags.name": "tag1"`, not array `"tags.name": [ "tag1" ]`. You will see **no document found** if you try using array – Koh Endru Aug 04 '21 at 06:33
  • nvm I forget to include $in. The query in mongodb should be `"tags.name": {$in: ["tag1", "tag2" ]}`. But it still return empty array in my code omg. – Koh Endru Aug 04 '21 at 06:44