These are chat archives for Automattic/mongoose

16th
Aug 2018
zedza
@zedsa
Aug 16 2018 02:26 UTC
when i set a key as unique like title: { type: String, unique: true }, that means only unique values will be saved for title, correct?
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 02:55 UTC
Yeah, you will get error about existing unique
Jack
@jackmercy
Aug 16 2018 03:01 UTC
Hi @lineus

const UserSchema = new mongoose.Schema({

    citizen_id: {
        type: String,
        required: true,
        unique: true
    },
    hashPassword: {
        type: String,
        required: true
    }
});

const CitizenSchema = new mongoose.Schema({
    Id_number: {
        type: String,
        required: true,
        unique: true
    },
    firstName: {
        type: String,
        required: true
    },
    lastName: {
        type: String,
        required: true
    }
});
if I have 3 citizen with Id_number : 1, 2, 3
Do we any solutions to check when we create a new user, their citizen_id must be in those 3 Id_number of CitizenSchema?
E.g If I create a new user with citizen_id 4 and save(). It will reject automatically
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 03:08 UTC
Do you mean, auto increment like in mysql?
Jack
@jackmercy
Aug 16 2018 03:12 UTC
No. I mean it will not allow you to save() any user with citizen_id outside those already have in Citizen collection.
sorry for my bad english
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 03:13 UTC
Right, want you to expand citizens in future?
If yes I'll give you dynamic 'checker'
If no, you can 'protect' it with simple if
var citizen = CitizenSchema.countDocuments({'Id_number': *yourGetVariable*}).exec();

citizen.then(n => {
 if (n > 0) {
 // your code goes here
 } else myErrorFunction('error msg, sorry wrong citizen')
})
Jack
@jackmercy
Aug 16 2018 03:14 UTC
in the future citizen will only save details of a person, user will save account information
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 03:17 UTC
countDocuments will retrun number of matching elements in this case citizen id, if this value is (> 0) that means citizen with given id exist
you can do else with error response
Jack
@jackmercy
Aug 16 2018 03:20 UTC
what about dynamic 'checker' ? I also want to learn about it.
I think right now countDocuments is what I need.
but I want to learn about dynamic 'checker' also. I've never hear about this technique
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 03:21 UTC
This is it
If you add another citizen with other Id countDocuments will also work (that's why you call it dynamic)
Jack
@jackmercy
Aug 16 2018 03:31 UTC
Thank @i-Clyde
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 03:35 UTC
Your welcome 🙂
Zakiir Juman
@zakiirjuman
Aug 16 2018 04:12 UTC
Hi Everyone. Mongoose seems to be trying to cast the _id field in one of the objects in my document on the replaceOne() function
the object is not defined as a mongoose schema, just an object,
I'm not seeing this issue on a regular save()
Zakiir Juman
@zakiirjuman
Aug 16 2018 04:30 UTC
turns out updateOne() was the better option for me, as I guess replaceOne() requires me to manually put an ID
Maurizio Bellemo
@mbellemo_twitter
Aug 16 2018 09:13 UTC

hi all... quick question from a noobie..
when I created the data model, I used the following structure to reference other objects...

company_id: {
        type: Schema.Types.ObjectId,
        required: true,
        ref: 'Company'
    },

without really knowing what is the use of the "ref" attribute... what would it be used for?

Kev
@lineus
Aug 16 2018 09:58 UTC
@mbellemo_twitter the ref path tells mongoose which collection to find() the referenced value in when you call .populate().
Maurizio Bellemo
@mbellemo_twitter
Aug 16 2018 12:27 UTC
@lineus sorry to ask... what is populate() and what would I use it for?
Kev
@lineus
Aug 16 2018 12:29 UTC
@mbellemo_twitter if you're familiar with mysql join, it's basically like that. here are the docs
Mathieu Vie
@Xipotera
Aug 16 2018 13:26 UTC

Hi everyone, i have a field where values looks like "ACM1", "ACM2", "ACMXX", "ACM146", ... i would like create the ACM147 for that i use this agregation :

[
    { 
        $project: {    
            idSubtring: {          
                $substrBytes: [            
                    "$externalId", 3, { 
                        $subtract: [ { $strLenBytes: "$externalId" }, 2    ] 
                    }          
                ]        
            }
        } 
    }, 
 { $group: {  
     _id: null,  
     max: {    $max: "$idSubtring"  }} 
     }
]

the problem it return max valeur as "99" not 146 i think i need to convert before make max but i don't know how? i'am trying using $toInt without result :(

Ben Chiciudean
@benydc
Aug 16 2018 13:55 UTC
is it possible to generate random IDs for a schema instead of incrementals?
Kev
@lineus
Aug 16 2018 17:31 UTC
@benydc There's not an easy way, but you can use the built-in generate method on the bson objectid prototype to pass in a date-like-Number to affect a part of the buffer that gets returned. here's a quick example
Ben Chiciudean
@benydc
Aug 16 2018 17:32 UTC
thanks
hillct
@hillct
Aug 16 2018 17:49 UTC
@lineus yes, I believe your example use of path().default is what I was looking for, but I was never able to locate it in the documentation. Did I just overlook it, or is it not documented fully?
Kev
@lineus
Aug 16 2018 18:01 UTC
@benydc my suggestion about using the generate method breaks part of the usefulness of mongodb bson ids, in that you won't be able to determine ( to the second ) when a doc was created by inspecting the id. If you're ok with that and you're ok with not having the machine fingerprint embedded in the id, you could just write a function to generate a random 24 character hex string for example
@hillct I'm not sure, I'll take a look at the docs.
hillct
@hillct
Aug 16 2018 18:28 UTC
@lineus I’m testing this functionality now, with no success. My schema defines a default, but it isn’t being retrieved as far as I can tell. My testing is thus far incomplete though. I’ll post when I hve more diffinative results
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 18:32 UTC
I've got an array of indexes is it possible to run a $pull action for all indexes?
E.g. 'user.icons.[0, 2, 61, 67].active': true
Kev
@lineus
Aug 16 2018 18:54 UTC
@i-Clyde can you share your schema definition for that path?
@hillct let me know if I can help :+1:
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 19:19 UTC
@lineus I want to set message.ID.INDEX.unread: to false or remove that option totally
Yesterday's schema:
  messageHistory: {
    type: Map,
    of: Array
  },
image.png
In multiple objects
hillct
@hillct
Aug 16 2018 19:47 UTC
@lineus the .default functionality does work as you indicated. My initial test methodology was flawed, and I’m having a rendering problem (unrelated to mongoose, similar to that described here https://groups.google.com/a/dartlang.org/forum/#!topic/web-ui/ZAc2eLUtb1A which probably relates to some arcane CSS interaction
Maurizio Bellemo
@mbellemo_twitter
Aug 16 2018 20:04 UTC
I am using a Schema for a User that requires a unique email (otherwise you could potentially register two Users with the same email). I thought I could just use unique validation, but it does not work out-of-the-box
var UserSchema = new Schema({
    email: {
        type: String,
        required: true,
        trim: true,
        unique: true,
        validate: {
            validator: (value) => {
                return validator.isEmail(value)
            },
            message: '{VALUE} is not a valid email'
        }
    },
    password: {
        type: String,
        required: true
    },
    roles: {
        type: [{
            type: String,
            enum: ['user', 'admin']
        }],
        default: ['user']
    },
    tokens: [{
        access: {
            type: String,
            required: true
        },
        token: {
            type: String,
            required: true
        }
    }],
    company_id: {
        type: Schema.Types.ObjectId,
        required: true,
        ref: 'Company'
    }
});
It actually does not perform any validaiton
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 20:58 UTC

@lineus nvm, I solved this problem with something like this:

      let msgs = res.messageHistory.get(pID);

      for (let i = 0, len = msgs.length; i < len; i++) {
        if (!isNaN(msgs[i]['unread']) && msgs[i]['unread'] === true) unsetq['messageHistory.'+ pID +'.'+ i +'.unread'] = '';
      }

      Player.update({'socketToken': socketID}, {$unset: unsetq } ).exec().catch((err) => {console.log(err)});

//$unset was the solution ❤

Kev
@lineus
Aug 16 2018 21:50 UTC
@i-Clyde sorry, I got tied up :/ I'm glad you sorted it out!
@mbellemo_twitter unique isn't a validator, it creates a unique index on the collection which prevents duplicate values for fields, but only after the index is completely created in mongodb. It's possible to insert documents with duplicate fields after the collection is created but before the indexing is done. This is a common source of confusion but it's documented here and also here
André Bomark
@ZwiFTi
Aug 16 2018 21:56 UTC
Can someone help me with this one: The combination of user and card has to be unique (usercard).
var detailSchema = new Schema({
    difficulty: { type: Number, required: true },
    usercard: {
        user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
        card: { type: mongoose.Schema.Types.ObjectId, ref: 'Card',  required: true }
    }
});
Kev
@lineus
Aug 16 2018 21:57 UTC
@mbellemo_twitter I ran into the same issue when I first started using mongoose/mongodb. You can use await Model.ensureIndexes() before saving docs to a new collection to ensure the index is ready to block duplicates.
André Bomark
@ZwiFTi
Aug 16 2018 21:57 UTC
I will have many users with the same ID, and many cards with the same ID, but it can only be one user with one card
Kev
@lineus
Aug 16 2018 22:00 UTC
@ZwiFTi you can create a compound unique index that looks at multiple fields.
André Bomark
@ZwiFTi
Aug 16 2018 22:08 UTC
Thanks @lineus
Kev
@lineus
Aug 16 2018 22:08 UTC
anytime :smile:
André Bomark
@ZwiFTi
Aug 16 2018 22:11 UTC
@ .index why is name and num 1? Could it be anything?
Kev
@lineus
Aug 16 2018 22:12 UTC
that's the default naming convention from mongodb, I'm not sure if you can override it or not. seems like a reasonable thing to do.
yeah, Schema.index() passes the options to the driver which takes a name option
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:17 UTC
how to group documents for date range like 20/07/2018 to 19/08/2018 and 20/06/2018 to 19/07/2018 and so on
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:18 UTC
I think you can do it with aggregate
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:19 UTC
i am able to do at month level
but not able to like this
[
{
$project: {
month: {$month: "$created_at"},
year: {$year: "$created_at"},
orderTotal : 1
}
},
{
$group: {
_id: {month : "$month" ,year : "$year" },
total: {$sum: "$orderTotal"},
count: {$sum: 1},
orders: {
$addToSet: "$_id"
}
}
}
]
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:20 UTC
I know what you feel
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:20 UTC
this will group by month
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:21 UTC
You can use ` for code highlight on gitter
André Bomark
@ZwiFTi
Aug 16 2018 22:21 UTC
@lineus Do you see what I am doing wrong, because I can still create with the same user id and card id: https://gist.github.com/ZwiFTi/2f566d11863c7212aa21f105fdecd95c
Kev
@lineus
Aug 16 2018 22:22 UTC
@ZwiFTi when you insert data are you first callingawait Detail.ensureIndexes()?
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:23 UTC
@i-Clyde : yes
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:23 UTC
you can use $gte and $lt in aggregate
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:23 UTC
but have just the cycle day
like 20
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:23 UTC
so I have an idea
use miliseconds
André Bomark
@ZwiFTi
Aug 16 2018 22:24 UTC
@lineus That is probably it kev, I'll give it a try
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:24 UTC
convert you schema from date to Number (I don't know how to store miliseconds in Date)
@lineus is here something like $pop for objects?
Kev
@lineus
Aug 16 2018 22:29 UTC
where it removes the path from the object and returns it to the caller?
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:29 UTC
just remove
(Select last object in an array and remove last key in this object)
Kev
@lineus
Aug 16 2018 22:30 UTC
not that I know of, you'll probably have to write that yourself
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:31 UTC
@i-Clyde : i have generate credit card report like thing
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:31 UTC
Alright then ^^
@yogeshbansal ?
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:31 UTC
user cycle start at 20th of each minth
month
and end of 19th of next month
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:32 UTC
I think set minutes, hours and seconds to 0
will help
Yogesh Bansal
@yogeshbansal
Aug 16 2018 22:32 UTC
i need to show the order between these days of each month
Mikołaj Chodorowski
@i-Clyde
Aug 16 2018 22:33 UTC
This solution is for chat message but I think it can help
    // Check when Msg Was sent
      function whenMsgWasSentPre(time) {
        let now = new Date();let x = new Date();x.setDate(x.getDate() - 1);function createOutput(n) {return('<div class="chat-date"><span>'+n+'</span></div>')}
        let then_f = new Date(time.getTime());then_f.setHours(0);then_f.setMinutes(0);then_f.setSeconds(0);
        let now_f = new Date();now_f.setHours(0);now_f.setMinutes(0);now_f.setSeconds(0);

        let days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
        let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
        let diffDays = Math.round((now_f.getTime() - then_f.getTime())/(24*60*60*1000));

        function isThisYear(one, two) {if ((one.getMonth() == two.getMonth()) && (one.getFullYear() == two.getFullYear())) return true; else return false}

        if ((time.getDate() == now.getDate()) && isThisYear(time, now)) return createOutput('Today');
        else if ((time.getDate() == x.getDate()) && (time.getFullYear() == now.getFullYear())) return createOutput('Yesterday');
        else if (((diffDays >= 0) && (diffDays < 7)) && (time.getFullYear() == now.getFullYear())) return createOutput(days[time.getDay()]);
        else if (((diffDays >= 7) && (diffDays < 365)) && (time.getFullYear() == now.getFullYear())) return createOutput(time.getDate()+' '+months[time.getMonth()]);
        else if ((time.getFullYear() != now.getFullYear())) return createOutput(time.getDate()+' '+months[time.getMonth()]+' '+time.getFullYear());
        else return(createOutput('In the future'))
      }
Im setting Hours, minutes and seconds to 0 and then I calculate the difference between the dates that gives me plain results
Kev
@lineus
Aug 16 2018 23:06 UTC
@yogeshbansal here's an example of using dates in aggregate mongoose doesn't cast values in aggregate the way it does in queries so it's a lot less forgiving to use dates in aggregation. Updated with $sort to make it more clear