I am trying to add an User object to my Game object's field "players_list", which is a list of User objects. This is what my Game object looks like:
{ players_list:
[ { games: [Array],
_id: '5b0e112ff13033792f08566f',
email: 'c',
password: '$2a$10$iWOBvVf4KAPwbH7zDczfYeI5iXI721jQ7bN1juJ4Us3R.Lqetmhfu',
handle: 'C',
__v: 0,
id: '5b0e112ff13033792f08566f' } ],
_id: '5b0e181aeb766e7bfaf2fb09',
players_status:
[ { _id: '5b0e181aeb766e7bfaf2fb0a',
playerId: '5b0e112ff13033792f08566f',
status: 'Joined' } ],
postGameEvaluation: [],
date: 'QQQQ',
time: 'QQQQ',
duration: 4,
players_needed: 4,
max_players: 4,
level: 4,
author:
{ games:
[ '5b0e13e69d35007a147578da',
'5b0e15b4b117987b00d68cb4',
'5b0e181aeb766e7bfaf2fb09' ],
_id: '5b0e112ff13033792f08566f',
email: 'c',
password: '$2a$10$iWOBvVf4KAPwbH7zDczfYeI5iXI721jQ7bN1juJ4Us3R.Lqetmhfu',
handle: 'C',
__v: 0,
id: '5b0e112ff13033792f08566f' },
__v: 0 }
and this is what my User objet looks like
{ games: [],
_id: 5b0e1820eb766e7bfaf2fb0b,
email: 'f',
password: '$2a$10$JmS.9axW8batMUKzE7OQx.GShdNDt09eArXfYGoI/DUWEKVwAn5ju',
handle: 'F',
__v: 0 }
I then run req.body.players_list.push(req.user) to add the User object to the player_list field of the Game object. This is what by req.body looks like after adding the User object:
{ players_list:
[ { games: [Array],
_id: '5b0e112ff13033792f08566f',
email: 'c',
password: '$2a$10$iWOBvVf4KAPwbH7zDczfYeI5iXI721jQ7bN1juJ4Us3R.Lqetmhfu',
handle: 'C',
__v: 0,
id: '5b0e112ff13033792f08566f' },
{ games: [],
_id: 5b0e1820eb766e7bfaf2fb0b,
email: 'f',
password: '$2a$10$JmS.9axW8batMUKzE7OQx.GShdNDt09eArXfYGoI/DUWEKVwAn5ju',
handle: 'F',
__v: 0 } ],
_id: '5b0e181aeb766e7bfaf2fb09',
players_status:
[ { _id: '5b0e181aeb766e7bfaf2fb0a',
playerId: '5b0e112ff13033792f08566f',
status: 'Joined' } ],
postGameEvaluation: [],
date: 'QQQQ',
time: 'QQQQ',
duration: 4,
players_needed: 4,
max_players: 4,
level: 4,
author:
{ games:
[ '5b0e13e69d35007a147578da',
'5b0e15b4b117987b00d68cb4',
'5b0e181aeb766e7bfaf2fb09' ],
_id: '5b0e112ff13033792f08566f',
email: 'c',
password: '$2a$10$iWOBvVf4KAPwbH7zDczfYeI5iXI721jQ7bN1juJ4Us3R.Lqetmhfu',
handle: 'C',
__v: 0,
id: '5b0e112ff13033792f08566f' },
__v: 0 }
So, I then update the Game object in mongo with Post.findByIdAndUpdate(req.params.id, req.body).then((result) => {..., but the result doesn't contain the new User. This is what my result looks like
{ players_list: [ 5b0e112ff13033792f08566f ],
_id: 5b0e181aeb766e7bfaf2fb09,
players_status:
[ { _id: 5b0e181aeb766e7bfaf2fb0a,
playerId: '5b0e112ff13033792f08566f',
status: 'Joined' } ],
postGameEvaluation: [],
date: 'QQQQ',
time: 'QQQQ',
duration: 4,
players_needed: 4,
max_players: 4,
level: 4,
author: 5b0e112ff13033792f08566f,
__v: 0 }
The strange thing is that if I leave my current React Component, and then go back into it (thus triggering fetchUser and fetchGame), then the Game fetched does have the new User in its players_list. Does this happen because the mongo update function is asynchronous? Even so, I thought that the .then((result) => { in Post.findByIdAndUpdate(req.params.id, req.body).then((result) => { made sure that Post.findByIdAndUpdate completed first before continuing
If you look at the docs: http://mongoosejs.com/docs/api.html#findbyidandupdate_findByIdAndUpdate you'll notice that findByIdAndUpdate returns the original object, not the updated doc. You have to pass in {new: true} as options for it to resolve with the updated object.
Related
I have a prisma query that returns users on a pivot table CommunityMember. The pivot table associates to the table User. As a result, my queries into the User table do not place the object user on top of the replies. I have a lot of functions designed to run with the user object on top so I am trying to figure out how to map user into my returns so the functions can run correctly. I've tried a lot of combinations of map and have had no luck. Do you all have any ideas?
Here is my prisma query:
members = await prisma.user.findMany({
select: {
id: true,
username: true,
name: true,
bio: true,
avatar: true,
},
skip: 10 * Number(page),
take: 10,
});
It gives a result like
members:
[{id: 2, username: 'man}, {id: 3, username: 'dan'}]
I want it to look like: members:
members:
[{user: {id: 2, username: 'man'}}, {user: {id: 3. username: 'dan'}}]
If I run members[0].user I should get the data inside. It seems like a simple map function, but I have not been able to get it to work.
Another example of what I get, but do not want.
members: [
{
id: 2,
username: 'man',
name: 'A Man',
bio: 'A man.',
avatar: [Object]
},
{
id: 3,
username: 'dude',
name: 'Dude',
bio: "Dude is a #1 developer.",
avatar: [Object]
},
This is what I want.
members: [
{
//Notice the user object on top of each entry
user: {
id: 2,
username: 'man',
name: 'A Man',
bio: 'Man.',
avatar: [Object]
}
},
{
user: {
id: 3,
username: 'dude',
name: 'Dude',
bio: "Dudes a #1 developer.",
avatar: [Object]
}
},
]
Not sure I got the whole picture but wouldn't this do?
const members = [
{
id: 2,
username: 'man',
name: 'A Man',
bio: 'A man.',
avatar: {}
},
{
id: 3,
username: 'dude',
name: 'Dude',
bio: "Dude is a #1 developer.",
avatar: {}
}
].map(member => ({user: member}))
if your object looks like:
obj = {members: [{...}, ..]}
then an Array.map will solve the problem:
const userMembers = obj.members.map((member) => ({user: member});
obj.members = userMembers;
I'm trying to create an object according to my model in mongoose using a controller, but I'm running into a problem that the last array nesting with prize patterns is not being written. Theoretically it is, but it is empty. I do not understand what the problem is, since I cannot add the necessary value to it even after creating the object through the constructor and after that doing something like: newGame.prizes = prizes;
With this behavior, all other properties within the prize property appear in the object, but the pattern array is empty.
Here is what my model looks like:
const GameSchema = mongoose.Schema({
type: String,
roundId: String,
userId: String,
calloutNumbersCount: Number,
tickets: [
{
id: String,
columns: [[Number]],
},
],
prizes: [
{
id: String,
name: String,
nameLocaleKey: String,
winAmount: Number,
patterns: [
{
type: String,
count: Number,
},
],
},
],
ticketPrice: Number,
boughtTicketIds: [String],
ended: Boolean,
});
Controller:
function createGame(gameType, userId) {
const currentGameConfig = config[gameType];
console.log("Controller");
currentGameConfig.prizes.map((el) => console.log(el.patterns));
const roundId = nanoid(LENGTH_OF_ROUND_ID);
const game = new Game({
type: currentGameConfig.type,
roundId,
userId,
calloutNumbersCount: currentGameConfig.callout.numbersCount,
tickets: [
{
id: 123, // temp
columns: [[0]], // temp
},
],
prizes: currentGameConfig.prizes,
ticketPrice: currentGameConfig.tickets.price,
boughtTicketIds: ["1", "2"], // temp
ended: false,
});
return game;
}
Place of creation and modification of the object in the route:
if (!game) {
const newGame = gameController.createGame(type, userId);
// newGame.prizes = currentGameConfig.prizes;
Game.addGame(newGame, (err, game) => {
if (err) {
res.json({ success: false, message: err.message });
throw err;
}
return res.json({
roundId: newGame.roundId,
});
});
}
Expected result:
The result:
EDITED
CurrentGameConfig:
{
type: 'BINGO_75',
name: 'Bingo 75',
nameLocaleKey: 'GAMES.BINGO_75',
prizes: [
{
name: 'Prize 1',
nameLocaleKey: 'PRIZES.BINGO_75.PRIZE_1',
winAmount: 10,
patterns: [Array]
},
{
name: 'Prize 2',
nameLocaleKey: 'PRIZES.BINGO_75.PRIZE_2',
winAmount: 10,
patterns: [Array]
},
{
name: 'Prize 3',
nameLocaleKey: 'PRIZES.BINGO_75.PRIZE_3',
winAmount: 10,
patterns: [Array]
},
{
name: 'Prize 4',
nameLocaleKey: 'PRIZES.BINGO_75.PRIZE_4',
winAmount: 10,
patterns: [Array]
},
{
name: 'Full house',
nameLocaleKey: 'PRIZES.BINGO_75.PRIZE_5',
winAmount: 10,
patterns: [Array]
}
],
tickets: { price: 10, quantity: 72, grid: { cols: [Object], rows: [Object] } },
callout: { numbersCount: 25 }
}
In node.js patterns look like [Array], but if display each pattern it look like:
[
{type: 'HORIZONTAL', count: 1},
{type: 'VERTICAL', count: 1},
{type: 'DIAGONAL', count: 1}
]
const arr = [
[
{
_id: "6136096f4255d84bcb4a7144",
user_id: "5fbfa729fc46a415ce5503a6",
picture: [Array],
timestamp: 1630931311227,
},
user: {
_id: "5fbfa729fc46a415ce5503a6",
first_name: "ABC",
last_name: "AAA",
picture: [Object]
}
],
[
{
_id: "613609414255d84bcb4a7122",
user_id: "5fbf6f91aff7f3320a906547",
picture: [Array],
device_platform: 'ios',
timestamp: 1630931265409
},
user: {
_id: "5fbf6f91aff7f3320a906547",
first_name: 'EEE',
last_name: 'TTT',
picture: [Object]
}
],
[
{
_id: "613709f49223350dfdaec618",
user_id: "5fbfa748fc46a415ce5503a8",
picture: [Array],
timestamp: 1630996980379
},
{
_id: "613609184255d84bcb4a710a",
user_id: "5fbfa748fc46a415ce5503a8",
picture: [Array],
timestamp: 1630931224383,
},
user: {
_id: "5fbfa748fc46a415ce5503a8",
first_name: 'GRT',
last_name: 'GGG',
picture: [Object]
}
]
]
I merged push into the object one were like res = [{_id: ..., user_id: ...},{_id: ..., user_id: ...}] and other one was like user = {_id: 5fbfa748fc46a415ce5503a8, first_name: 'AAA',last_name : 'DD'}
res.user = user;
array.push(res)
I merged two object it bring up this but it does not seems to be correct response.
when I used var merged = [].concat.apply([], arr); it does not work
how to fix with correct format.
Working code! just remove the user key from the array, and one note ) use const/let instead of var
const arr = [
[
{
_id: "6136096f4255d84bcb4a7144",
user_id: "5fbfa729fc46a415ce5503a6",
picture: [Array],
timestamp: 1630931311227,
},
{
_id: "5fbfa729fc46a415ce5503a6",
first_name: "ABC",
last_name: "AAA",
picture: [Object]
}
],
[
{
_id: "613609414255d84bcb4a7122",
user_id: "5fbf6f91aff7f3320a906547",
picture: [Array],
device_platform: 'ios',
timestamp: 1630931265409
},
{
_id: "5fbf6f91aff7f3320a906547",
first_name: 'EEE',
last_name: 'TTT',
picture: [Object]
}
],
[
{
_id: "613709f49223350dfdaec618",
user_id: "5fbfa748fc46a415ce5503a8",
picture: [Array],
timestamp: 1630996980379
},
{
_id: "613609184255d84bcb4a710a",
user_id: "5fbfa748fc46a415ce5503a8",
picture: [Array],
timestamp: 1630931224383,
},
{
_id: "5fbfa748fc46a415ce5503a8",
first_name: 'GRT',
last_name: 'GGG',
picture: [Object]
}
]
]
const merged = [].concat.apply([], arr);
console.log(merged);
I have the following schema:
const MenuSchema = new mongoose.Schema({
name: String,
type: String,
children: [{ type: ObjectId, ref: 'Menu' }],
});
And the following query:
const res = await Menu.aggregate([
{ $graphLookup: { from: "menus", startWith: "$children", connectToField: "children", connectFromField: "_id", as: "menus" }}
]);
As you can see, the menu schema is a self-referential data structure, children stores references to other instances of the same entity, with a 'type' field to differentiate the levels. I'm attempting to find and populate documents for each array of children (which are just BSON IDs) and return the results.
The above example seems to get most of the way there, however when I access one of the populated menus, it has a list of all the populated children in a flattened array, it doesn't retain the relationship structure.
For example, if I print out res, I get:
[ {
_id: 5f1212d053e5494bb45f18f3,
children: [ 5f1212d053e5494bb45f18f1 ],
name: 'Vodka',
type: 'Item',
__v: 0,
menus: [ [Object], [Object], [Object], [Object] ]
},
{
_id: 5f1212d053e5494bb45f18f4,
children: [ 5f1212d053e5494bb45f18f3, 5f1212d053e5494bb45f18f2 ],
name: 'Drinks',
type: 'Category',
__v: 0,
menus: [ [Object], [Object] ]
},
{
_id: 5f1212d053e5494bb45f18f5,
children: [ 5f1212d053e5494bb45f18f4 ],
name: 'Main Menu',
type: 'Menu',
__v: 0,
menus: [ [Object] ]
}
]
But when I print out res[1].menus, I get:
[
{
_id: 5f1212d053e5494bb45f18f3,
children: [ 5f1212d053e5494bb45f18f1 ],
name: 'Vodka',
type: 'Item',
__v: 0
},
{
_id: 5f1212d053e5494bb45f18f1,
children: [ 5f1212d053e5494bb45f18f0 ],
name: 'Double',
type: 'Variant',
__v: 0
},
{
_id: 5f1212d053e5494bb45f18f4,
children: [ 5f1212d053e5494bb45f18f3, 5f1212d053e5494bb45f18f2 ],
name: 'Drinks',
type: 'Category',
__v: 0
}
]
Which is all of the children in a flat array.
Is $graphLookup the correct approach, or am I just using it wrong?
I don't know if you are still looking for the answer for this, but if you use mongoose you can take advantage of the populate feature and use it as a middleware
Here's an example:
Let's say I want a list of people and their friends, and their friends-friends, etc. The result should look like this:
[
{
_id: "abc123",
name: "John Doe",
friends: [
{
_id: "efg456",
name: "Foo bar",
friends: [
{
_id: "hij789",
name: "Jane Doe",
friends: [more friends...]
}
]
}
]
]
In the db they are stored like this
{_id: "abc123", name: "John Doe", friends: ["efg456"]}
{_id: "efg456", name: "Foo bar", friends: ["hij789"]}
{_id: "hij789", name: "Jane Doe", friends: [more friends...]}
Your schema and middleware would be:
const Person = new Schema<Folder>({
name: {type: String, required: true},
friends: [{type: Schema.Types.ObjectId, ref: "person"}],
}, {timestamps: true})
Person.pre("find", function(next) {
this.populate("friends")
next()
})
Adding the function as a middleware to find will make it run for every person found. That includes the children in the friends array.
This question already has answers here:
Querying after populate in Mongoose
(6 answers)
Aggregation filter after $lookup
(1 answer)
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 4 years ago.
I have two models, Game and User. Game model is
const GameSchema = new Schema({
date: String,
time: String,
duration: Number, // minutes
location: [{ type: Schema.Types.ObjectId, ref: 'Court' }],
players_needed: Number,
max_players: Number,
level: Number,
players_list: [{ type: Schema.Types.ObjectId, ref: 'User' }], // players_list: [{ type: String }],
players_status: [{ playerId: String, status: String }], // status -joined or evaluted
postGameEvaluation: [{ playerId: String, evaluations: { } }],
author: { type: Schema.Types.ObjectId, ref: 'User' },
});
and User model is
const UserSchema = new Schema({
email: { type: String, unique: true, lowercase: true },
password: { type: String },
handle: { type: String }, // handle: { type: String, unique: true, lowercase: true },
games: [{ type: Schema.Types.ObjectId, ref: 'Post' }], // games and status
});
And I am trying to check if a User is already in the players_list of a Game using this
if (req.body.players_list.filter((e) => { return e._id === req.user._id; }).length > 0) {
.....
However, even when the User is already in the game, the if statement fails to check it. For example, here are two instances of a Game and User object where the if statement fails. This is the Game object
{ location: [],
players_list:
[ { games: [],
_id: '5b0cb9ff4a9c6a536d075f48',
email: 'efafesfse',
password: '$2a$10$bo1q0udXhL5ZnA9PMUZX4ufR0w0tcL5TmDARqAT5RpqfXheVtK3v2',
handle: 'FSEFSEFSE',
__v: 0,
id: '5b0cb9ff4a9c6a536d075f48' },
{ games: [Array],
_id: '5b0cba164a9c6a536d075f4b',
email: 'poi',
password: '$2a$10$sk.d5npeUMz0H9aQ6TKVzOir1j54UuXtdtQPIrxbKkwzPP07ODW/y',
handle: 'POI',
__v: 0,
id: '5b0cba164a9c6a536d075f4b' },
{ games: [Array],
_id: '5b0cba164a9c6a536d075f4b',
email: 'poi',
password: '$2a$10$sk.d5npeUMz0H9aQ6TKVzOir1j54UuXtdtQPIrxbKkwzPP07ODW/y',
handle: 'POI',
__v: 0,
id: '5b0cba164a9c6a536d075f4b' },
{ games: [Array],
_id: '5b0cbcd74a9c6a536d075f4e',
email: 'bv',
password: '$2a$10$BTvyzp9EnauZkODsg5010e/OUafNmjRbmAvJ33RslHbT.qiWTY4WC',
handle: 'BV',
__v: 0,
id: '5b0cbcd74a9c6a536d075f4e' } ],
_id: '5b0cba094a9c6a536d075f49',
players_status:
[ { _id: '5b0cba094a9c6a536d075f4a',
playerId: '5b0cb9ff4a9c6a536d075f48',
status: 'Joined' } ],
postGameEvaluation: [],
date: 'VVVVV',
time: 'VVVVVVV',
duration: 4,
players_needed: 4,
max_players: 4,
level: 4,
author:
{ games: [],
_id: '5b0cb9ff4a9c6a536d075f48',
email: 'efafesfse',
password: '$2a$10$bo1q0udXhL5ZnA9PMUZX4ufR0w0tcL5TmDARqAT5RpqfXheVtK3v2',
handle: 'FSEFSEFSE',
__v: 0,
id: '5b0cb9ff4a9c6a536d075f48' },
__v: 0 }
And here is the User object that is already in the players_list of the game but the if statement fails to check for it
{ games: [ 5b0cba094a9c6a536d075f49 ],
_id: 5b0cbcd74a9c6a536d075f4e,
email: 'bv',
password: '$2a$10$BTvyzp9EnauZkODsg5010e/OUafNmjRbmAvJ33RslHbT.qiWTY4WC',
handle: 'BV',
__v: 0 }