These are chat archives for Automattic/mongoose

28th
Nov 2017
scare4face
@scare4face
Nov 28 2017 16:39
@joeytwiddle wow thanks for the tip
scare4face
@scare4face
Nov 28 2017 16:44
i have a form with four inputs with data to be rendered to the view. how do i collect the data from the form on submit by just using express. any help? kinda new to forms tho
Tom
@goto1
Nov 28 2017 17:50

i have the following structure in my document…

{
  _id: ‘abcd1234’,
  episodes: [ { eId: ‘e1234’ }, { eId: ‘e4567’ } ]
}

not sure if i am doing this correctly, but the following returns the entire episodes array, with both e1234 and e4567 in the result

User.find({ _id: ‘abcd1234’ })
  .where(‘episodes.eId’).equals(‘e1234’)
  .exec()

any ideas?

Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:27
@goto1 you need elementMatch
Tom
@goto1
Nov 28 2017 22:28
i did elementMatch, what I am looking for is filtering capabilities… this obviously is not the filtering but rather returning ALL documents that match the query
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:29
you need to project only one object from array :)
Tom
@goto1
Nov 28 2017 22:29
i had to read the docs 10x before fully understanding what it actually does lol
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:29
projection -> elemMatch :)
it is quite easy
Tom
@goto1
Nov 28 2017 22:29
there might be multiple objects with the eId equal to e1234
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:30
it should match them all
Tom
@goto1
Nov 28 2017 22:30
it matches all docs that match the query
but the resulting array will consist of all items in the array for that doc
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:30
not if you use elemMatch in projection :)
Tom
@goto1
Nov 28 2017 22:30
so then i have to do doc.array.filter(item => item.eId === eId) type of thing
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:31
consider this
Tom
@goto1
Nov 28 2017 22:31
but that will only return a single item, i will need multiple ones, that could potentially have the attribute of eId equal to e1234

this is possible

[ { eId: ‘1234’ }, { eId: ‘1234’ }, { eId: ‘4567’ } ]

eId is neither the primary key nor unique

Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:32

User.find({ _id: ‘abcd1234’ }, { episodes: { $elemMatch: { eId: 1234  } } })
  .exec()
let me test this
Tom
@goto1
Nov 28 2017 22:32
that only returns the first item
it says in the docs
The $elemMatch operator limits the contents of an <array> field from the query results to contain only the first element matching the $elemMatch condition.
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:33
yes you are right
there was change regarding that as well
Tom
@goto1
Nov 28 2017 22:34
yeah its some crazy thing i need to do to accomplish what i want to do, so its prob easier to just do it programmatically
which is the solution i opted in for, thanks anyway!
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:36
sec
i m curious now
this is kind of what I wanted to accomplish, as per the answer on this thread
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:39
can you use aggregation ?
Tom
@goto1
Nov 28 2017 22:41
i am not entirely sure what aggregation does in mongoose, its hard to follow these docs sometimes lol
as per the docs…
Mongoose#Aggregate()

The Mongoose Aggregate constructor
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:43
db.notes.aggregate(
    // Pipeline
    [
        // Stage 1
        {
            $match: {
            _id: ObjectId("5a1bdb6a632c90001ece96fe")
            }
        },

        // Stage 2
        {
            $project: {
                history: {
                        $filter: {
                           input: "$history",
                           as: "item",
                           cond: { $eq: [ "$$item.title", "ut volutpat sapien" ] }
                        }
                     },
               title: 1,
            }
        },
    ]
);
i tested this now in 3T studio ... and it works
where my history is your episodes
and it iterates trough each element and execute $eq operator
Tom
@goto1
Nov 28 2017 22:45
right, so it will return multiple history sub-docs, right? all with the title of ut volutpat sapien… correct?
in case i remove last $filter pipe
i have 3 objects thre
Tom
@goto1
Nov 28 2017 22:47
cool, thanks a lot! i will definitely try this out
much appreciated!
i wonder about the performance difference between this and doing it programmatically
its prob better to just delegate this type of work to mongodb though
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:50
User.aggregate([
 {
   $match : {
    _id: 'abcd1234'
   }
 },
 $filter: {
  episodes: {
            $filter: {
               input: "$episodes",
               as: "item",
               cond: { $eq: [ "$$item.eId", 1234 ] }
            }
         },
   title: 1,
}
])
something like this :) @goto1
if data set is huge... than better candidate is Aggregation
Tom
@goto1
Nov 28 2017 22:50
thanks a lot! reading the docs on mongodb on aggregation to better understand this trick then will try it out
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:50
if it is not huge, it does not matter
Tom
@goto1
Nov 28 2017 22:51
yeah, it might get large, so i will prob switch to aggregation
thanks, i appreciate the help!
Vlado Tesanovic
@vladotesanovic
Nov 28 2017 22:52
nothing,
hopes everything will work
Tom
@goto1
Nov 28 2017 22:53
i am sure this will do the trick, thanks :clap: