These are chat archives for Automattic/mongoose

5th
Sep 2018
Mohamed Dhaker Abdeljawed
@Mdhaker
Sep 05 2018 11:40

I have a schema like this:

new mongoose.Schema({
// all participant of discussion
contributors:[
    { 
        user:{ type: mongoose.Schema.Types.ObjectId, ref: 'user',required:true },
        status:{type:String,enum:["shown","hidden"],default:"shown"}
    }],
// message list
messages : [MessageSchema],
createdAt: {
    type: Date,
    default: new Date()
},
updatedAt: 
    {
        type: Date
    },
// last message sent (to tree the discussion by last update)
lastMessage:
    {
        type:Date
    },
path: {type:String},}, { versionKey: false,strict:false });

I would like to compare the user objectId values in the query with a flat array with $all, is there a way to extract the values of "contributors.user" to be flat ? a map function or somthing that could help doing the query. at the end I want to find documents that matches contributors array, and I just have a flat table with Ids.

any way to compare flat array with complex array of objects
Kev
@lineus
Sep 05 2018 12:22

@Mdhaker your query should succeed as long as the array in the $all operator matches one of these conditions:
1) values that are valid objectids,
2) values that are hex strings of valid object ids,
3) values that are objects with a valid _id property

Here is a gist that shows a test for all three variants

Kev
@lineus
Sep 05 2018 12:28
if you call mongoose.set('debug', true) right before the three calls to runQuery() you'll see that in the first query the ObjectIds are just passed through as is, and in both the second and third calls mongoose casts the $all array to an array of ObjectIds.
Mohamed Dhaker Abdeljawed
@Mdhaker
Sep 05 2018 12:30
@lineus I didn't know array.map() is a valid mongodb query ! I will try it
Kev
@lineus
Sep 05 2018 12:37

array.prototype.map() returns a new array, so the value passed in to the query is an array, not strictly array.map().
This example shows what I mean:

#!/usr/bin/env node
'use strict';

function run(value) {
  console.log('run is running.');
  if(!Array.isArray(value)) {
    throw new Error('value was not an array');
  }
}

function getArray() {
  console.log('getArray is running.');
  return [];
}

run(getArray());

Output:

gitter: ./mdhaker2.js
getArray is running.
run is running.
gitter:
when you pass a function call as a parameter to another function, the function parameter is run first and the value it returns is passed in as the value to the funciton.
Mohamed Dhaker Abdeljawed
@Mdhaker
Sep 05 2018 12:39
Yes, I miss understand already and you are still comparing flat to flat ! arr is a flat name Array ! I don't have problem with the id type, but the arrays format !
the object array is in the mongodb document, and the flat one will be passed in the query
I'm looking to flatten the array in mongo in order to compare with my query array
I'm currently checking a aggregate solution with $unwind
Kev
@lineus
Sep 05 2018 12:50
Oh, I see. You have an array of embedded docs with a user property that stores the objectid. This gist more accurately represents your use case
@Mdhaker ^
Kev
@lineus
Sep 05 2018 12:55
the gist shows that you don't need to flatten the array on the server side. It will work just by passing the path 'contributers.user' and your flat array of ids should be enough.
Mohamed Dhaker Abdeljawed
@Mdhaker
Sep 05 2018 12:57
your saying that I can use a simple query $all with 'contributers.user' ?
Kev
@lineus
Sep 05 2018 12:58
I'm not just saying it, that second gist shows the actual output from doing it :smile:
Mohamed Dhaker Abdeljawed
@Mdhaker
Sep 05 2018 12:59
lol thanks, I'm not testing the gist anyway, just working on my code :D
It's just because i still didn't see an array of nested object "arr" , its flat in the two gists
Kev
@lineus
Sep 05 2018 13:04
in the second gist I changed my schema to make arr be an array of nested objects with a user property and added a map function to add the objects to arr with a user property per the schema.
i also changed the query path as described above to be 'arr.user' and kept everything else the same.
here is the same gist with arr changed to contributers to further mimic your schema . I also changed one of the tests to look for the other document in this collection.
Mohamed Dhaker Abdeljawed
@Mdhaker
Sep 05 2018 13:09
@lineus nice, thanks I just noticed the query update
Kev
@lineus
Sep 05 2018 13:11
I wasn't 100% sure that it would work with { 'contributers.user': { $all : [] } } either. I learned something too :smile: Thanks for asking a really interesting question!