Florian Ludewig
Florian Ludewig

Reputation: 6002

Mongoose Find All Documents Matching a Substring of Inputs

Suppose you have this array of fileNames:

[
    'filename1_c4d.rar',
    'text122_octane.c4d',
    'texture1.png',
    'texture2.png',
]

And in my database I have a collection of Tags:

[
    {
        _id: 'id1',
        name: 'cinema4d',
        aliases: ['.c4d', 'c4d', 'cinema4d'],
    },
    {
        _id: 'id2',
        name: 'octane',
        aliases: ['octane'],
    },
    {
        _id: 'id3',
        name: 'textures',
        aliases: ['texture', 'textures'],
    },
    // ...
]

My goal is to fetch all Tags that have a substring of my fileNames in aliases, with the help of mongoose. (Tags.find({ someFancyQuery: fileNames }))


Here is an example to make it better understandable:

I have this fileName: filename1_c4d.rar. Based on this name the query should be able to fetch the Tag with the name cinema4d, because it's aliases include a substring of the fileName filename1_c4d.rar

So those fileNames should fetch the following Tags:


So in the end the result of the query should be those Tags (without duplicated):

cinema4d, octane, textures


P.S.: To explain what this is for:

A user can upload e.g. a .rar file and I want to automatically assign tags based on the filenames, that are inside the .rar file.


I hope it's clear what my goal is. Please let me know if there is somewthing you don't understand.

Upvotes: 2

Views: 424

Answers (1)

Saravana
Saravana

Reputation: 12817

you need to use aggregation pipeline to compare alias is substring of input array

db.t5.aggregate([
        {$addFields :{tags: tags, matches : {$map:{input: "$aliases", as: "a", in: {$map : {input: tags, as: "i", in: {$gte:[{$indexOfCP:["$$i", "$$a"]},0]}}}}}}}, 
        {$addFields: {matchez :{$reduce : {input : "$matches", initialValue : [], in: { $concatArrays: [ "$$value", "$$this" ] }}}}}, 
        {$match: {"matchez" : {$in : [true]}}}, 
        {$group : {_id: null, names : {$addToSet : "$name"}}}
    ])

result

{ "_id" : null, "names" : [ "octane", "textures", "cinema4d" ] }

sample collection

> db.t5.find()
{ "_id" : "id1", "name" : "cinema4d", "aliases" : [ ".c4d", "c4d", "cinema4d" ] }
{ "_id" : "id2", "name" : "octane", "aliases" : [ "octane" ] }
{ "_id" : "id3", "name" : "textures", "aliases" : [ "texture", "textures" ] }
{ "_id" : "id4" }
{ "_id" : "id5" }
{ "_id" : "id6" }

input tags

> tags
[
        "filename1_c4d.rar",
        "text122_octane.c4d",
        "texture1.png",
        "texture2.png"
]

result

> db.t5.aggregate([{$addFields :{tags: tags, matches : {$map:{input: "$aliases", as: "a", in: {$map : {input: tags, as: "i", in: {$gte:[{$indexOfCP:["$$i", "$$a"]},0]}}}}}}}, {$addFields: {matchez :{$reduce : {input : "$matches", initialValue : [], in: { $concatArrays: [ "$$value", "$$this" ] }}}}}, {$match: {"matchez" : {$in : [true]}}}, {$group : {_id: null, names : {$addToSet : "$name"}}}])
{ "_id" : null, "names" : [ "octane", "textures", "cinema4d" ] }
>

Upvotes: 1

Related Questions