sails js many to many associations not working - sails.js

User.js
module.exports = {
tableName: 'user',
attributes: {
firstName: {
type: 'string',
},
lastName: {
type: 'string',
},
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
pets: { //integer
collection:'pet',
via:'owners'
}
}
};
================================
Pet.js
------
module.exports = {
tableName: 'pet',
attributes: {
id: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
breed: {
type: 'string',
},
type: {
type: 'string',
},
name: {
type: 'string',
},
owners: { //integer
collection:'user',
via:'pets'
}
}
};
But when i hit the blueprint api http://localhost:1337/user or http://localhost:1337/pet i dont get associated records
Here is the output in ARC or postman for user and pet
[
{
"pets": [],
"firstName": "a",
"lastName": "aa",
"id": 1
},
{
"pets": [],
"firstName": "b",
"lastName": "bb",
"id": 2
},
{
"pets": [],
"firstName": "c",
"lastName": "cc",
"id": 3
},
{
"pets": [],
"firstName": "d",
"lastName": "dd",
"id": 4
},
{
"pets": [],
"firstName": "e",
"lastName": "ee",
"id": 5
}
],
[
{
"owners": [],
"id": 1,
"breed": "dalmatian",
"type": "male",
"name": "tom"
},
{
"owners": [],
"id": 2,
"breed": "labrador",
"type": "female",
"name": "kg"
},
{
"owners": [],
"id": 3,
"breed": "doberman",
"type": "male",
"name": "tq"
},
{
"owners": [],
"id": 4,
"breed": "puppy",
"type": "male",
"name": "yu"
}
]
One to many association works fine but don't know what am i missing in many to many ?
i tried removing the id column from both the models but that didn't help

Try to add a pet to an owner with the add Blueprint API:
POST /:model/:id/:association/:fk
example :
http://localhost:1337/user/1/pets/2
This will add the pet with id 2 to the owner with id 1.

Related

RangeError (end): Invalid value: Only valid value is 0: 1 when generating model

Getting the error RangeError (end): Invalid value: Only valid value is 0: 1 when generating model when I try to generate model
Expected Behavior
when I use this command get generate model on match_details with assets/models/to_get/match_details.json
it should be creating a model inside the match_details folder with the fields inside the JSON file mentioned.
Current Behavior
When I try to do this I get the error RangeError (end): Invalid value: Only valid value is 0: 1 when generating model** when I try to generate model
Possible Solution
Am sure it is something about parsing the JSON file
More info
here is what the JSON file looks like
{
"success": true,
"details": {
"id": 22,
"date_time": "2022-04-12T20:00:00Z",
"home_team": {
"id": 69,
"home_strip": {
"id": 15,
"image": "/uploads/strip_5_0py3QXM.png"
},
"away_strip": {
"id": 16,
"image": "/uploads/WhatsApp_Image_2022-03-09_at_10.24.56_AM.jpeg"
},
"players": [{
"id": 47,
"is_cap": false,
"average_skill": 3,
"region": {
"id": 13,
"name_ar": "التجمع الخامس",
"name_en": "Fifth Settlement",
"state": {
"id": 8,
"name_ar": "القاهره",
"name_en": "Cairo"
}
},
"first_name": "Ezz El Din",
"last_name": "Karim",
"mobile": "01113481110",
"email": null,
"image": null,
"positions_ar": [{
"مدافع": 3
}],
"positions_en": [{
"CB": 3
}],
"basic_skills_ar": [{
"السرعة": 4
},
{
"تمرير الكرة": 3
},
{
"تسديد": 2
}
],
"basic_skills_en": [{
"speeding": 4
},
{
"Passing": 3
},
{
"shooting": 2
}
]
}],
"cap": {
"id": 46,
"is_cap": true,
"average_skill": 3,
"region": {
"id": 13,
"name_ar": "التجمع الخامس",
"name_en": "Fifth Settlement",
"state": {
"id": 8,
"name_ar": "القاهره",
"name_en": "Cairo"
}
},
"first_name": "Karim",
"last_name": "Garrana",
"mobile": "01113332257",
"email": "karim.garrana#gmail.com",
"image": null,
"positions_ar": [{
"مهاجم": 3
},
{
"مدافع": 4
}
],
"positions_en": [{
"ST": 3
},
{
"CB": 4
}
],
"basic_skills_ar": [{
"السرعة": 3
},
{
"تمرير الكرة": 3
},
{
"تسديد": 3
}
],
"basic_skills_en": [{
"speeding": 3
},
{
"Passing": 3
},
{
"shooting": 3
}
]
},
"average_skill": 3,
"points": 0,
"name": "كوبرا",
"league": 25,
"logo": "/uploads/9_IApeihR.png",
"region_ar": "التجمع الخامس",
"region_en": "Fifth Settlement"
},
"away_team": {
"id": 68,
"home_strip": {
"id": 14,
"image": "/uploads/strip_6.png"
},
"away_strip": {
"id": 13,
"image": "/uploads/strip_5.png"
},
"players": [{
"id": 46,
"is_cap": true,
"average_skill": 3,
"region": {
"id": 13,
"name_ar": "التجمع الخامس",
"name_en": "Fifth Settlement",
"state": {
"id": 8,
"name_ar": "القاهره",
"name_en": "Cairo"
}
},
"first_name": "Karim",
"last_name": "Garrana",
"mobile": "01113332257",
"email": "karim.garrana#gmail.com",
"image": null,
"positions_ar": [{
"مهاجم": 3
},
{
"مدافع": 4
}
],
"positions_en": [{
"ST": 3
},
{
"CB": 4
}
],
"basic_skills_ar": [{
"السرعة": 3
},
{
"تمرير الكرة": 3
},
{
"تسديد": 3
}
],
"basic_skills_en": [{
"speeding": 3
},
{
"Passing": 3
},
{
"shooting": 3
}
]
}],
"cap": {
"id": 45,
"is_cap": false,
"average_skill": 4,
"region": {
"id": 11,
"name_ar": "ميامى",
"name_en": "Miami",
"state": {
"id": 7,
"name_ar": "الإسكندرية",
"name_en": "Alexandria"
}
},
"first_name": "Ahmed",
"last_name": "Wagdi",
"mobile": "01207199086",
"email": "ahmed.w.amin#gmail.com",
"image": "/uploads/90f1e1c9-b430-4f9c-8347-a86be57f58676954964268664537546.jpg",
"positions_ar": [{
"مدافع": 5
}],
"positions_en": [{
"CB": 5
}],
"basic_skills_ar": [{
"تسديد": 5
},
{
"تمرير الكرة": 5
},
{
"السرعة": 5
}
],
"basic_skills_en": [{
"shooting": 5
},
{
"Passing": 5
},
{
"speeding": 5
}
]
},
"average_skill": 4,
"points": 2,
"name": "المنتقمون",
"league": 25,
"logo": "/uploads/6.png",
"region_ar": "التجمع الخامس",
"region_en": "Fifth Settlement"
},
"location": {
"id": 8,
"name_ar": "مدرسة الكابيتال",
"name_en": "Capital School",
"location": "30.014650515430546,31.4582347869873",
"region": 13
}
}
}

validate if documents have same data as I send

I've the following documents in database: (each document is a room with members)
[
{
"id": "room1",
"members": [{
"id": "member1",
"acks": "XXX",
},{
"id": "member2",
"acks": "XXX",
},{
"id": "member3",
"acks": "XXX",
},{
"id": "member4",
"acks": "XXX",
}]
},
{
"id": "room2",
"members": [{
"id": "memberA",
"acks": "XXX",
},{
"id": "memberB",
"acks": "XXX",
},{
"id": "memberC",
"acks": "XXX",
},{
"id": "memberD",
"acks": "XXX",
},{
"id": "memberE",
"acks": "XXX",
},{
"id": "memberF",
"acks": "XXX",
}]
},
{
"id": "room3",
"members": [{
"id": "memberX",
"acks": "XXX",
},{
"id": "memberY",
"acks": "XXX",
},{
"id": "memberZ",
"acks": "XXX",
}]
}
]
Sending from frontend next data:
[{
"id": "room1"
"members": ["member1", "member2"]
},{
"id": "room2"
"members": ["memberA", "memberB", "memberC", "memberF"]
},{
"id": "room3"
"members": ["memberX", "memberY"]
}]
I want to check if all members match for each room and return an unique boolean as a response --> True if all match and False if is someone that doesn't match.
This data should return false:
[{
"id": "room1"
"members": ["memberA", "member2"] //Because memberA is not in room1
},{
"id": "room2"
"members": ["memberA", "memberB", "memberC", "memberF"]
},{
"id": "room3"
"members": ["memberX", "memberY"]
}]
Playground
Is it possible to achieve it with one query?
Thank you very much in advance.
You can try a query,
Prepare your query request from frontend request
// consider this is your request parameter
let request = [{
"id": "room1",
"members": ["member1", "member2"]
},{
"id": "room2",
"members": ["memberA", "memberB", "memberC", "memberF"]
},{
"id": "room3",
"members": ["memberX", "memberY"]
}];
// prepare query
let query = request.map((r) => {
return {
id: r.id,
members: r.members.map((m) => {
return { "members.id": m }
})
}
});
console.log(query)
Try countDocuments function and get total count of rooms with request
async function hasRooms (query) {
let count = await Schema.countDocuments({ $or: query });
return (count === request.length);
}
Playground
Use your function
console.log(await hasRooms(query));

mongoose ref only returns one element inside array

I am trying to reference an array of categories but output is only returning one element inside.
here is the post model, I'm I am wondering about post_categories that has a ref to Category
here is the post model
import mongoose from 'mongoose'
mongoose.set('debug', true)
const postSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: false,
ref: 'User'
},
post_title: {
type: String,
trim: true,
min: 3,
max: 160,
required: true
},
post_slug: {
type: {},
unique: true,
index: true
},
post_excerpt: {
type: String,
max: 1000
},
post_content: {
type: {},
required: true
},
post_thumbnail: {
data: Buffer,
contentType: String
},
post_comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
require: false
}],
post_tags: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Tag',
require: false
}],
post_categories: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Category'
}
],
post_meta_title: {
type: String,
required: false
},
post_meta_description: {
type: String,
required: false
},
post_meta_keywords: [{
type: String,
required: false
}],
allow_comments: {
type: Boolean,
required: false,
default: 1,
},
allow_search_engines: {
type: Boolean,
required: false,
default: 1
},
published: {
type: Boolean,
required: false,
default: 0
}
}, {
timestamps: true
})
const Post = mongoose.model('Post', postSchema)
export default Post
this is from the post controller
const getPosts = asyncHandler(async (req, res) => {
const posts = await Post.find().populate('post_categories')
res.json(posts)
})
this is the category model, I'm thinking the problem is within the post controller or the post model though.
import mongoose from 'mongoose'
const categorySchema = mongoose.Schema({
name: {
type: String,
required: true
},
post_count: {
type: Number,
default: 0
}
}, {
timestamps: true
})
const Category = mongoose.model('Category', categorySchema)
export default Category
here is output with the populate
[
{
"post_comments": [
"60257ffd6b08fb4334078b56"
],
"post_tags": [],
"post_categories": [
{
"post_count": 2,
"_id": "602148846168c7408831ac4c",
"name": "Category One",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.647Z",
"updatedAt": "2021-02-19T05:55:45.944Z"
}
],
"post_meta_keywords": [],
"allow_comments": true,
"allow_search_engines": true,
"published": false,
"_id": "602148846168c7408831ac49",
"post_title": "Post One",
"post_excerpt": "Post one excerpt",
"post_content": "This is post one content blah blah blah",
"post_slug": "post-one",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.606Z",
"updatedAt": "2021-02-08T14:19:48.606Z"
},
{
"post_comments": [
"6025e1150d215935688d68ba",
"6025e1150d215935688d68bb"
],
"post_tags": [
"602148846168c7408831ac51",
"602148846168c7408831ac52"
],
"post_categories": [
{
"post_count": 2,
"_id": "602148846168c7408831ac4d",
"name": "Category Two",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.647Z",
"updatedAt": "2021-02-19T05:55:46.053Z"
}
],
"post_meta_keywords": [],
"allow_comments": true,
"allow_search_engines": true,
"published": false,
"_id": "602148846168c7408831ac4a",
"post_title": "Post Two",
"post_excerpt": "Post Two excerpt",
"post_content": "This is post two content blah blah blah",
"post_slug": "post-two",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.606Z",
"updatedAt": "2021-02-08T14:19:48.606Z"
},
{
"post_comments": [],
"post_tags": [],
"post_categories": [
{
"post_count": 2,
"_id": "602148846168c7408831ac4c",
"name": "Category One",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.647Z",
"updatedAt": "2021-02-19T05:55:45.944Z"
}
],
"post_meta_keywords": [],
"allow_comments": true,
"allow_search_engines": true,
"published": false,
"_id": "602148846168c7408831ac4b",
"post_title": "Post Three",
"post_excerpt": "Post three excerpt",
"post_content": "This is post three content blah blah blah",
"post_slug": "post-three",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.606Z",
"updatedAt": "2021-02-08T14:19:48.606Z"
}
]
that output only shows one category however if I show the output without populate it shows all the categories
[
{
"post_comments": [
"60257ffd6b08fb4334078b56"
],
"post_tags": [],
"post_categories": [
"602148846168c7408831ac4c"
],
"post_meta_keywords": [],
"allow_comments": true,
"allow_search_engines": true,
"published": false,
"_id": "602148846168c7408831ac49",
"post_title": "Post One",
"post_excerpt": "Post one excerpt",
"post_content": "This is post one content blah blah blah",
"post_slug": "post-one",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.606Z",
"updatedAt": "2021-02-08T14:19:48.606Z"
},
{
"post_comments": [
"6025e1150d215935688d68ba",
"6025e1150d215935688d68bb"
],
"post_tags": [
"602148846168c7408831ac51",
"602148846168c7408831ac52"
],
"post_categories": [
"60342fbdfb8c6a0db2aecf00",
"602148846168c7408831ac4d"
],
"post_meta_keywords": [],
"allow_comments": true,
"allow_search_engines": true,
"published": false,
"_id": "602148846168c7408831ac4a",
"post_title": "Post Two",
"post_excerpt": "Post Two excerpt",
"post_content": "This is post two content blah blah blah",
"post_slug": "post-two",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.606Z",
"updatedAt": "2021-02-08T14:19:48.606Z"
},
{
"post_comments": [],
"post_tags": [],
"post_categories": [
"6021479b255d7a3360d4bffa",
"602148846168c7408831ac4c"
],
"post_meta_keywords": [],
"allow_comments": true,
"allow_search_engines": true,
"published": false,
"_id": "602148846168c7408831ac4b",
"post_title": "Post Three",
"post_excerpt": "Post three excerpt",
"post_content": "This is post three content blah blah blah",
"post_slug": "post-three",
"__v": 0,
"createdAt": "2021-02-08T14:19:48.606Z",
"updatedAt": "2021-02-08T14:19:48.606Z"
}
]

How do return the count of a particular field in psql db

I have a database tables with the relationships as below.
Cagetory ---> CategorItems //One to many(CategoryItem has categoryId colum)
CatgeoryItems ---> Post // One to many(Post has categoryItemId).
I want to count the total number of records in Post groupBy the categoryItemId also returning along the categoryItem name, and the categoryName. I want columns like returned
CategoryName, item, totalInPostTable
I am using sequelize rdb mapper. When i use the query below
models.Post.findAll({
include: [{
model: models.CategoryItem,
attributes: ['item'],
required: true,
include: [{
model: models.Category,
attributes: ['name'],
required: true,
group: ["name"]
}]
}],
attributes: ['categoryItemId'],
})
It returns the record below
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 1,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 2,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
},
{
"categoryItemId": 4,
"CategoryItem": {
"item": "xxxxxx",
"Category": {
"name": "xxxxxx"
}
}
}
However,it failed and return null without error as soon as i groupBy the categpryItem id like below.
models.Post.findAll({
include: [{
model: models.CategoryItem,
attributes: ['item', [sequelize.fn('COUNT', sequelize.col('id')), 'no_category']],
required: true,
include: [{
model: models.Category,
attributes: ['name'],
required: true,
}]
}],
attributes: ['categoryItemId'],
group: ["categoryItemId"]
})
Pls what am i doing wrong ? ANy help would be appreciated.

simplifying deep nested mongo query without using aggregate

I'm trying to create a sort of newsfeed feature for my app. I'm trying to understand how to do it with a nested query in Mongo/Mongoose rather than using aggregate. (the rest of the app uses nested queries) and I'd prefer to not have to modify the query with vanilla javascript to get the perfect object if I don't need to.
I'd like to get the friends of the current user, for each friend, get all of their posts and then sort it all by date.
I want to make my current query more efficient as there's an extra step
my query in Mongoose
User.findOne({ _id: req.userId }, 'friends.user -_id')
.populate({
path: 'friends.user',
model: 'User',
select: 'posts -_id',
populate: {
path: 'posts',
model: 'Post',
select: 'date author user desc -_id',
options: { sort: { date: -1 } },
populate: {
path: 'author user',
model: 'User',
select: 'profile.firstname profile.lastname profile.avatar username'
},
},
})
the results
{
"newsfeed": [
{
"user": {
"posts": [
{
"user": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "kenne"
},
"author": {
"profile": {
"firstname": "user1",
"lastname": "user1",
"avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
},
"_id": "5b562382a16cde19638e4bee",
"username": "user1"
},
"date": "2018-07-24T06:40:37.413Z",
"desc": "sdfsdf"
},
{
"user": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"author": {
"profile": {
"firstname": "user1",
"lastname": "user1",
"avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
},
"_id": "5b562382a16cde19638e4bee",
"username": "user1"
},
"date": "2018-07-24T06:40:17.180Z"
},
{
"user": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"author": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"date": "2018-07-23T22:20:15.246Z",
"desc": "Gibberish"
}
]
}
},
{
"user": {
"posts": [
{
"user": {
"profile": {
"firstname": "user3",
"lastname": "user3",
"avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
},
"_id": "5b5382f3661a8d7023e1ae65",
"username": "user3"
},
"author": {
"profile": {
"firstname": "user3",
"lastname": "user3",
"avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
},
"_id": "5b5382f3661a8d7023e1ae65",
"username": "user3"
},
"date": "2018-07-21T19:09:45.543Z",
"desc": "Gibberish"
}
]
}
}
]
}
because I need to first get the friends of the user, the current query creates two user objects each with their own posts and authors and user objects within them.
eg. {"newsfeed": [{"user": {"bios": [...]}}], [{"user": {"bios": [...]}}] }
what I want is something like this
{
"newsfeed": [{
"posts": [
{
"user": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"author": {
"profile": {
"firstname": "user1",
"lastname": "user1",
"avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
},
"_id": "5b562382a16cde19638e4bee",
"username": "user1"
},
"date": "2018-07-24T06:40:37.413Z",
"desc": "sdfsdf"
},
{
"user": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"author": {
"profile": {
"firstname": "user1",
"lastname": "user1",
"avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
},
"_id": "5b562382a16cde19638e4bee",
"username": "user1"
},
"date": "2018-07-24T06:40:17.180Z"
},
{
"user": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"author": {
"profile": {
"firstname": "user2",
"lastname": "user2",
"avatar": "c66620a0ef057908a1663725956ac03a.jpg"
},
"_id": "5b56549fcba9231e5d1e848d",
"username": "user2"
},
"date": "2018-07-23T22:20:15.246Z",
"desc": "Gibberish"
},
{
"user": {
"profile": {
"firstname": "user3",
"lastname": "user3",
"avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
},
"_id": "5b5382f3661a8d7023e1ae65",
"username": "user3"
},
"author": {
"profile": {
"firstname": "user3",
"lastname": "user3",
"avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
},
"_id": "5b5382f3661a8d7023e1ae65",
"username": "user3"
},
"date": "2018-07-21T19:09:45.543Z",
"desc": "Gibberish"
}
]}
How can I do that without using aggregate? to get something more like this
eg. {"newsfeed": [{"posts": [...]}] }
additional info
users
const UserSchema = new Schema({
username : String,
friends : [{ user: { type: Schema.Types.ObjectId, ref: 'User'}, status: String }],
profile: {
name : String,
firstname : String,
lastname : String,
avatar : String
}),
posts : [{ type: Schema.Types.ObjectId, ref: 'Post' }]
});
posts
const PostsSchema = new Schema({
user : { type: Schema.Types.ObjectId, ref: 'User' },
author : { type: Schema.Types.ObjectId, ref: 'User' },
date : Date,
desc : String
});
example data: users
{
"_id" : ObjectId("5b51fd2a3f4ec33546a06648"),
"profile" : {
"firstname" : "user1",
"lastname" : "user1"
"avatar" : "user1.png"
}
"username" : "user1",
"friends" : [
{
"_id" : ObjectId("5b51fd7c3f4ec33546a0664f"),
"user" : ObjectId("5b51fd643f4ec33546a0664c")
},
{
"_id" : ObjectId("5b51fdb53f4ec33546a06655"),
"user" : ObjectId("5b51fd903f4ec33546a06652")
}
]
}
{
"_id" : ObjectId("5b51fd643f4ec33546a0664c"),
"profile" : {
"firstname" : "user2",
"lastname" : "user2"
"avatar" : "user2.png"
}
"posts" : [
{
"_id" : ObjectId("5b51fdcd3f4ec33546a06610"),
"_id" : ObjectId("5b51fdcd3f4ec33546a06611"),
"_id" : ObjectId("5b51fdcd3f4ec33546a06612"),
}
],
"__v" : 5,
"username" : "user2"
},
{
"_id" : ObjectId("5b51fd903f4ec33546a06652"),
"profile" : {
"firstname" : "user3",
"lastname" : "user3"
"avatar" : "user3.png"
},
"posts" : [
{
"_id" : ObjectId("5b51fdce3f4ec33546a06615"),
"_id" : ObjectId("5b51fd2a3f4ec33546a06617")
}
],
"__v" : 5,
"username" : "user3"
}
example date: posts
{
"_id" : ObjectId("5b51fdcd3f4ec33546a06610"),
"user" : ObjectId("5b51fd2a3f4ec33546a06648"),
"author" : ObjectId("5b51fd2a3f4ec33546a06648"),
"date" : ISODate("2018-07-20T15:18:02.962Z"),
"desc" : "user1 gibberish",
"__v" : 0
}
{
"_id" : ObjectId("5b51fdcd3f4ec33546a06611"),
"user" : ObjectId("5b51fd643f4ec33546a0664c"),
"author" : ObjectId("5b51fd643f4ec33546a0664c"),
"date" : ISODate("2018-07-20T15:19:00.968Z"),
"desc" : "user2 gibberish",
"__v" : 0
}
{
"_id" : ObjectId("5b51fdcd3f4ec33546a06612"),
"user" : ObjectId("5b51fd903f4ec33546a06652"),
"author" : ObjectId("5b51fd903f4ec33546a06652"),
"date" : ISODate("2018-07-20T15:19:44.102Z"),
"desc" : "user3 gibberish",
"__v" : 0
}
{
"_id" : ObjectId("5b51fdce3f4ec33546a06615"),
"user" : ObjectId("5b51fd643f4ec33546a0664c"),
"author" : ObjectId("5b51fd643f4ec33546a0664c"),
"date" : ISODate("2018-07-20T15:19:00.968Z"),
"desc" : "more gibberish",
"__v" : 0
}
{
"_id" : ObjectId("5b51fdce3f4ec33546a06616"),
"user" : ObjectId("5b51fd903f4ec33546a06652"),
"author" : ObjectId("5b51fd903f4ec33546a06652"),
"date" : ISODate("2018-07-20T15:19:44.102Z"),
"desc" : "more gibberish",
"__v" : 0
}
You could try unrolling the items in the application layer with the following code
User.find({ _id: mongoose.Types.ObjectId("5b51fd2a3f4ec33546a06648") }, 'friends.user -_id')
.populate({
path: 'friends.user',
model: 'User',
select: 'posts -_id',
})
.exec(function(err, results) {
// Post.find({ _id: {$in: results
const postIDs = results.reduce((acc, user) => {
return acc.concat(
...user.friends.map(
friend => friend.user.posts
)
)
}, [])
Post.find({ _id: { $in: postIDs } })
.populate(
{
path: 'author user',
model: 'User',
select: 'profile.firstname profile.lastname profile.avatar username'
}
)
.exec(function(err, posts) {
console.log(
JSON.stringify(posts, null, 2)
);
})
});
Other option is map reduce, but since you don't like aggregation, I'm not sure map reduce is appropriate either.
const mapReduceConfig = {
map: function() {
var friends = this.friends;
emit(
this._id,
friends.reduce(
(acc, friend) => {
return acc.concat(
friend.posts &&
friend.posts.reduce((pacc, p) => pacc.concat(p), [])
) || [];
},
[]
)
);
},
reduce: function(k, vals) {
return Array.sum(vals);
}
};
User.mapReduce(mapReduceConfig, function(err, results) {
console.log(
JSON.stringify(results, null, 2)
);
});