mongoose ref only returns one element inside array - mongodb

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"
}
]

Related

MongoDB sort by multiple fields on boolean type

First of all i need "isFavourite": true then "isReadByPro": false and then updatedAt:-1.
I tried below way but not working.
{ $sort: { updatedAt: -1 } },
{ $sort: { isReadByPro: 1 } },
{ $sort: { isFavourite: -1 } },
[
{
"_id": "628c8378c92d4b969cf4b53b",
"post": {
"title": "project 94608"
},
"isFavourite": true,
"isReadByPro": true,
"updatedAt": "2022-06-06T10:34:05.776Z"
},
{
"_id": "628f507192034120c7fc261a",
"post": {
"title": "your payment test 1"
},
"isFavourite": true,
"isReadByPro": true,
"updatedAt": "2022-05-27T10:39:16.493Z"
},
{
"_id": "628f50a792034120c7fc2681",
"post": {
"title": "your payment test 3"
},
"isFavourite": true,
"isReadByPro": true,
"updatedAt": "2022-05-27T08:42:48.403Z"
},
{
"_id": "628c76840ffe2cd088654d50",
"post": {
"title": "showcase 1"
},
"isFavourite": false,
"isReadByPro": true,
"updatedAt": "2022-05-24T06:10:38.364Z"
},
{
"_id": "628c780a0ffe2cd088654e21",
"post": {
"title": "project 1 test"
},
"isFavourite": false,
"isReadByPro": true,
"updatedAt": "2022-05-27T06:30:54.058Z"
},
{
"_id": "628c79cb5b4b0ee6020482df",
"post": {
"title": "project 2 test"
},
"isFavourite": false,
"isReadByPro": true,
"updatedAt": "2022-05-27T06:30:54.058Z"
}
]
In order to sort by multiple fields, they should be on the same sorting object. The order of them is according to priority. This data is sorted first by isFavourite, then, all the documents with the same isFavourite value will be sorted between them by isReadByPro and so on.
{ $sort: {isFavourite: -1, isReadByPro: 1, updatedAt: -1} }

Group multiple times in aggregation framework keeping multiple fields

I need to group multiple time a collection keeping multiple fields.
I've tried $group in aggregation framework but I probably make a mistake because I can't keep the different fields I need.
Here is the example:
[
{
"courseTitle": "Master 1",
"courseCompleted": false,
"module_id": "m01",
"section": "01 - Introduction",
"order": 1,
"completed": true,
"moduleTitle": "Module 1"
},
{
"courseTitle": "Master 1",
"courseCompleted": false,
"module_id": "m02",
"section": "01 - Introduction",
"order": 2,
"completed": true,
"moduleTitle": "Module 2"
},
{
"courseTitle": "Master 1",
"courseCompleted": false,
"module_id": "m03",
"section": "01 - Introduction",
"order": 3,
"completed": false,
"moduleTitle": "Module 3"
},
{
"courseTitle": "Master 1",
"courseCompleted": false,
"module_id": "m04",
"section": "02 - First test",
"order": 4,
"completed": false,
"moduleTitle": "Module 4"
}
]
I need to group first by section and then by courseTitle AND courseCompleted fields:
[
{
"courseTitle": "Master 1",
"courseCompleted": false,
"sections": [
{
"section": "01 - Introduction",
"modules": [
{
"module_id": "m01",
"order": 1,
"completed": true,
"moduleTitle": "Module 1"
},
{
"module_id": "m02",
"order": 2,
"completed": true,
"moduleTitle": "Module 2"
},
{
"module_id": "m03",
"order": 3,
"completed": false,
"moduleTitle": "Module 3"
},
]
},
{
"section": "02 - First test",
"modules": [
{
"module_id": "m04",
"order": 4,
"completed": false,
"moduleTitle": "Module 4"
}
]
}
]
}
]
Example in playground: https://mongoplayground.net/p/ThqXLYmQTCe
You need to run $group in order to get nested array:
db.collection.aggregate([
{
$group: {
_id: { courseTitle: "$courseTitle", section: "$section", courseCompleted: "$courseCompleted" },
modules: { $push: { module_id: "$module_id", order: "$order", completed: "$completed", moduleTitle: "$moduleTitle" } }
}
},
{ $sort: { "_id.section": 1 } },
{
$group: {
_id: { courseCompleted: "$_id.courseCompleted", courseTitle: "$_id.courseTitle" },
sections: { $push: { section: "$_id.section", modules: "$modules" } }
}
},
{
$project: {
_id: 0,
courseTitle: "$_id.courseTitle",
courseCompleted: "$_id.courseCompleted",
sections: 1
}
}
])
Mongo Playground

Delete objects inside NESTED JSONB arrays with PostgreSQL

json Request:
INSERT INTO test.demotbl (data)
VALUES ('{
"x1": "Americas",
"x2": "West",
"x3": [{
"x_id": "sam"
}],
"x4": {
"a1": true,
"a2": false,
"a3": [
"xx",
"xx"
],
"a4": [
"Josh"
],
"y1": [{
"id": "RW",
"z2": true,
"z3": "USER",
"z4": [{
"name": "john"
}]
},
{
"id": "RO",
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "salin"
}
{
"id": "DBA",
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "Samule"
}]
}
]
}
}'::jsonb)
Question 1 :how can i delete the the array values where "id":"RO" from y1 array ?
There can be any no of element in the y1 json array i want to delete the array value based on id condition.
how can i delete the the array values where "id":"RO" from y1 array ?
There can be any no of element in the y1 json array i want to delete the array value based on id condition.
Expected Output after deleting:
{
"x1": "Americas",
"x2": "West",
"x3": [{
"x_id": "sam"
}],
"x4": {
"a1": true,
"a2": false,
"a3": [
"xx",
"xx"
],
"a4": [
"Josh"
],
"y1": [{
"id": "RW",
"z2": true,
"z3": "USER",
"z4": [{
"name": "john"
}]
},
{
"id": "DBA",
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "Samule"
}]
}
]
}
}
Question 2 : How can i only delete the "id":"RO" from the y1 array
Expected Output:
{
"x1": "Americas",
"x2": "West",
"x3": [{
"x_id": "sam"
}],
"x4": {
"a1": true,
"a2": false,
"a3": [
"xx",
"xx"
],
"a4": [
"Josh"
],
"y1": [{
"id": "RW",
"z2": true,
"z3": "USER",
"z4": [{
"name": "john"
}]
},
{
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "salin"
}
{
"id": "DBA",
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "Samule"
}]
}
]
}
}
Edit note: I misunderstood the question. Thought you wanted to delete the whole object containing 'RO'. I edited the answer so as just to delete the id.
There is a small error in the jsonb object you provide. It should probably look like this:
{
"x1": "Americas",
"x2": "West",
"x3": [{
"x_id": "sam"
}],
"x4": {
"a1": true,
"a2": false,
"a3": [
"xx",
"xx"
],
"a4": [
"Josh"
],
"y1": [{
"id": "RW",
"z2": true,
"z3": "USER",
"z4": [{
"name": "john"
}]
},
{
"id": "RO",
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "salin"
}]
},
{
"id": "DBA",
"z2": false,
"z3": "SELECT",
"z4": [{
"name": "Samule"
}]
}
]
}
}
With that said, this should work, but keep in mind - this will replace all entries in the working table. The jsonb objects are in the field "field".
with zd as (select ('{x4,y1,'||index-1||',id}')::text[] as path
from table
,jsonb_array_elements((field->>'x4')::jsonb->'y1')
with ordinality arr(x,index)
where x->>'id'='RO'
)
update table set field=
field #- zd.path
from zd
Best regards,
Bjarni

sails js many to many associations not working

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.

Need help in mongodb $pull

I have a mongodb document that is like this:
{
"_id": ObjectId("5231718f042f8bc215000007"),
"ApplicationId": "YVo9bEQiDLg2",
"Network": {
"Millennial Media": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 352,
"App": [
{
"AppId": "APID - Banner",
"AppValue": "76970",
"Priority": 100
}
]
},
"Buzzcity": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 353,
"App": [
{
"AppId": "Partner ID",
"AppValue": "80624",
"Priority": 100
}
]
},
"Adiquity": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 354,
"App": [
{
"AppId": "package",
"AppValue": "com.ristomobile.giftntake",
"Priority": 0
},
{
"AppId": "Site ID",
"AppValue": "adqkkqkk-14eo91zj-qv6qt",
"Priority": 100
},
{
"AppId": "appName",
"AppValue": "Gift&Take",
"Priority": 0
}
]
},
"Smaato": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 351,
"App": [
{
"AppId": "Adspace ID",
"AppValue": "65766605",
"Priority": 100
}
],
"Partner": [
{
"PartnerId": "Publisher ID",
"PartnerValue": "923862008"
}
]
},
"AdNear": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 367,
"Partner": [
{
"PartnerId": "pubid",
"PartnerValue": "rs-1328"
},
{
"PartnerId": "api_key",
"PartnerValue": "RSW78:QH8HHM389M7YP"
}
]
},
"twinpine": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 371,
"Partner": [
{
"PartnerId": "pid",
"PartnerValue": "1551a74d1df075a"
},
{
"PartnerId": "alid",
"PartnerValue": "405"
}
]
},
"Vserv.mobi": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 370,
"Partner": [
{
"PartnerId": "Zone Id",
"PartnerValue": "32024"
},
{
"PartnerId": "Publisher Id",
"PartnerValue": "12649"
}
]
}
},
"LastUpdate": ISODate("2013-06-24T01:44:22.865Z")
}
and i tried to pull away the Millenial Media data:
db.MediationSetup.update(
{
ApplicationId: "YVo9bEQiDLg2"
},
{
$pull: {
Network: {
"Millennial Media": {
"Active": true,
"RefreshInterval": 300000,
"NetworkId": 352,
"App": [
{
"AppId": "APID - Banner",
"AppValue": "76970",
"Priority": 100
}
]
}
}
}
})
but it gives
Cannot apply $pull/$pullAll modifier to non-array
I am puzzled, I am indeed pulling an array! so what is going on?
When I understood you correctly, you want to remove an entry from the array in Network.Millennial Media.App. In that case you have to reference a field nested in sub-documents by using the dot-notation:
db.MediationSetup.update(
{
ApplicationId: "YVo9bEQiDLg2"
},
{
$pull: { "Network.Millennial Media.App": {
"AppId": "APID - Banner",
"AppValue": "76970",
"Priority": 100
}
}
});