These are chat archives for Automattic/mongoose

14th
Mar 2018
Johnny Wu
@wxs77577
Mar 14 2018 01:43
hi, I store a user's id in user_id,and I can populate the user to user_id but I wanna keep
user_id as the raw id and populate the user to another VIRTUAL fielf
field like 'user', how can I do that?
Kev
@lineus
Mar 14 2018 07:13
@wxs77577 what do you mean by raw id ? Is user_id a bson ObjectID?
Johnny Wu
@wxs77577
Mar 14 2018 07:57
@lineus output like: {user_id: "asdf123asdf123fds", "user": {"_id": "asdf123asdf123fds", "nickname": "Johnny"}}
I don't wanna populate modify user_id to an user object
I've found out on github. use virtual
Mihajlo Ilijić
@Pritilender
Mar 14 2018 08:48
You'd define user as a virtual and mark user_id as local_field.
Johnny Wu
@wxs77577
Mar 14 2018 08:49
@Pritilender yeah, now I use virtual field
Mihajlo Ilijić
@Pritilender
Mar 14 2018 08:50
Ok :)
Bruno Barros
@bybrunobarros
Mar 14 2018 08:56
Hey everyone! What is the most efficient / convenient way to retrieve a subdocument by another attribute than _id? Subdocuments have a ìsFeatured` flag, and I'd like to filter it sooner, than later.
Chris Hurst
@ytsruh
Mar 14 2018 09:11
@bybrunobarros use any other field that is indexed and query that field
Bruno Barros
@bybrunobarros
Mar 14 2018 09:13
@ytsruh Do you mean something like this (I haven't tried yet obviously) parent.findOne({isFeatured: true})?
Chris Hurst
@ytsruh
Mar 14 2018 09:15
@bybrunobarros assuming you have indexed isFeatured then yes
if a field isnt indexed then the DB has to go through every record, an index is kind of like a snapshot of a field
so by going over every record it loses the 'effeciency' that you were looking for
Bruno Barros
@bybrunobarros
Mar 14 2018 09:17
Ok I didn't think about indexing boolean flags, I'll have a look. Maybe I'll filter afterward.
@ytsruh thanks
Salvatore Tedde
@microcipcip
Mar 14 2018 09:18
Hi guys, does anybody know the answer to my question here on Stackoverflow? https://stackoverflow.com/questions/49245949/mongoose-set-ref-on-loose-schema
Chris Hurst
@ytsruh
Mar 14 2018 09:18
@bybrunobarros no issues. An index will always be quicker than a standard query. But there are memory/performance downsides too remember
Bruno Barros
@bybrunobarros
Mar 14 2018 09:19
Yes, that's why I'm going to "have a look" :)
Mihajlo Ilijić
@Pritilender
Mar 14 2018 09:22
@microcipcip What's your schema definition? It looks ok to me to do what you want. Have you tried it out?
Salvatore Tedde
@microcipcip
Mar 14 2018 09:24
But am I able to populate without a for loop? I mean with await db.page.findOne({ _id: myId }).populate('img')?
ATM I am in a Page schema and there I have a pageIds ObjectId from the Image schema
Chris Hurst
@ytsruh
Mar 14 2018 09:25
@microcipcip why not do one query and then map a new array?
Salvatore Tedde
@microcipcip
Mar 14 2018 09:26
So you mean I loop through it and populate manually?
Mihajlo Ilijić
@Pritilender
Mar 14 2018 09:26
From my understanding of Mongoose, I don't see why you couldn't do that single populate.
Salvatore Tedde
@microcipcip
Mar 14 2018 09:26
How does he know what collection to populate if there is no ref?
Mihajlo Ilijić
@Pritilender
Mar 14 2018 09:27
That's why I asked you about your schema, I don't know what you have or not :D And why are you using strict: false in the first place?
Salvatore Tedde
@microcipcip
Mar 14 2018 09:28
Ok I'll post it here
My pageSchema.... ignore validation rules
const pageSchema = schema(
  joi.object({
    title: joi.string().required(),
    roles: joi.string().allow(''),
    public: joi.boolean().required(),
    slug: joi.string(),
    published: joi.boolean().required(),
    model: joi.string().required().meta({
      type: 'ObjectId',
      ref: 'Model'
    }),
    createdBy: joi.string().required(),
  }),
  {
    strict: false,
    timestamps: true,
    minimize: false,
  }
)
These are required fields, but I have many more that are added dinamically
Mihajlo Ilijić
@Pritilender
Mar 14 2018 09:30
how mare? 100 more or less than 10 more?
If I were in your place, I'd define every field upfront.
Salvatore Tedde
@microcipcip
Mar 14 2018 09:30
Basically it depend on the model
I have built a CMS
Depending on the model field it will change the number of fields there
so I could have image fields, textarea fields etc etc
take a look at this
you can state ref there
but I don't know how good decision is going with this approach
Salvatore Tedde
@microcipcip
Mar 14 2018 09:33
But I can't set up the schema in the route AFAIK?
Imagine for example an express route
Mihajlo Ilijić
@Pritilender
Mar 14 2018 09:34
My approach to non-required fields is to define the whole model upfront, stating what is minimal required fields.
Salvatore Tedde
@microcipcip
Mar 14 2018 09:35
Umm ok
I guess the only solution I have is to loop through each property then
Mihajlo Ilijić
@Pritilender
Mar 14 2018 09:36
If the fields are not user generated, then I don't see why would you have any problem with stating what fields are possible. You could also use discriminated schema from Mongoose for even easier querying.
Salvatore Tedde
@microcipcip
Mar 14 2018 09:37
I have a Page model that changes from page to page
for example I may have a page with model services and one with model portfolio
they will have different custom fields
Kev
@lineus
Mar 14 2018 09:38
have you successfully compiled a schema (mongoose.model()) defined this way @microcipcip ?
Salvatore Tedde
@microcipcip
Mar 14 2018 09:38
The only solution I have found so far is a for loop in the route
const pageObj = page.toJSON()
for (const field in pageObj) {
  const fieldEl = pageObj[field]
  if (fieldEl.type === 'imageEl') {
    for (const [i, pageId] of fieldEl.pageIds.entries()) {
      fieldEl.pageIds[i] = await db.image.findOne({ _id: pageId })
    }
  }
}
Yes because I have strict: false
So I am allowed to add fields at will
Kev
@lineus
Mar 14 2018 09:42
#!/usr/bin/env node
'use strict'

const joi = require('joi')
const mongoose = require('mongoose')

const x = joi.object({
  title: joi.string().required(),
  roles: joi.string().allow(''),
  public: joi.boolean().required(),
  slug: joi.string(),
  published: joi.boolean().required(),
  model: joi.string().required().meta({
    type: 'ObjectId',
    ref: 'Model'
  }),
  createdBy: joi.string().required()
}, { strict: false })

const M = mongoose.model('test', x)

const m = new M({
  title: '234',
  roles: '234',
  public: true,
  slug: '234',
  published: true,
  model: '234',
  createdBy: '234'
})

console.log(m)

output:

gitter: ./wtf.js 
/Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/schema.js:602
    throw new TypeError('Undefined type `' + name + '` at `' + path +
    ^

TypeError: Undefined type `undefined` at `isJoi`
  Did you try nesting Schemas? You can only nest using refs or arrays.

what am I doing wrong to make this work?

Salvatore Tedde
@microcipcip
Mar 14 2018 09:43
You can try without Joi I don't think it is necessary
I am using joigoose which is a plugin
Kev
@lineus
Mar 14 2018 09:44
interesting, didn't know that was a thing.
It is not related to my issue though
it's just a schema validator
Kev
@lineus
Mar 14 2018 09:45
yeah, I wasn't trying to solve your issue :) just lurk-learning.
Salvatore Tedde
@microcipcip
Mar 14 2018 09:47
Ah ok ;)
Prasad nv
@prasad47
Mar 14 2018 12:12
@kev can you look into my Issue
@lineus let me know if you need any additional info
Bruno Barros
@bybrunobarros
Mar 14 2018 14:27
Hey everyone! Is it possible to populate an embedded document? await testimony[0].populate('org').execPopulate() is stalled. testimony[0] is an EmbeddedDocument. Am I missing something?
Mihajlo Ilijić
@Pritilender
Mar 14 2018 14:35
@bybrunobarros is testimony[0] model or id?
Bruno Barros
@bybrunobarros
Mar 14 2018 14:37
@Pritilender I don't really understand the question 🤔 it's an embedded document. What do you mean? It's definitely not an id attribute.
I guess that testimony is array of ids on some schema, so what am I asking is have you done MySchema.find({}).populate('testimony') or not?
Bruno Barros
@bybrunobarros
Mar 14 2018 14:39
@Pritilender Actually it's not an array of reference ids, they are "real" subdocuments.
Mihajlo Ilijić
@Pritilender
Mar 14 2018 14:39
oooh, ok
Bruno Barros
@bybrunobarros
Mar 14 2018 14:41
I'd like to populate only one testimony's org (testimony[0] in my example) and not all the testimonies' org.
Mihajlo Ilijić
@Pritilender
Mar 14 2018 14:41
I don't know if that's doable...
Bruno Barros
@bybrunobarros
Mar 14 2018 14:42
Maybe not. It's too bad if you can populate a document, but not a subdocument.
Mihajlo Ilijić
@Pritilender
Mar 14 2018 14:44
You can populate a subdocument, but I'm not sure if you can populate a particular subdocument.
Try .populate('testimony.org')
It should work, but it will populate all testimony subdocuments, and not just testimony[0]
Bruno Barros
@bybrunobarros
Mar 14 2018 14:45
Yes, I'd prefer not, but it's not really a big deal.
Mihajlo Ilijić
@Pritilender
Mar 14 2018 14:46
You can write a neat aggregation query with $lookup stage which will take only first testimony and populate it
But that's more mongo approach, not mongoose
Bruno Barros
@bybrunobarros
Mar 14 2018 14:48
Well I'll think about all the solutions :)
thanks
Mihajlo Ilijić
@Pritilender
Mar 14 2018 14:49
Damn, I now get it what you want and what testimony[0] is...
Yeah, it's weird if it's not possible to do .populate on subdoc...
Sorry for the missunderstanding from my part.
Bruno Barros
@bybrunobarros
Mar 14 2018 14:50
No worries, it's more my explanation in a few words
Bruno Barros
@bybrunobarros
Mar 14 2018 15:19
@Pritilender Well finally I did this testimony[0].org = await Org.findById(testimony[0].id)