Retrieving related elements from MongoDB - reactjs

I have the following data in MongoDB. Based alone on an id that I have available how can I retrieve all other entries where the player matches the player for my current id.
For example : find who the player for id 12 is, search all other entries that match that player name and return a list of all of them.
[
{_id: '62ecdf342f1193134043964c', id: '12', player: 'David Beckham', team: 'Manchester United'},
{_id: '62ecdf342f1193134043965c', id: '17', player: 'Cristiano Rolando', team: 'Manchester United'},
{_id: '62ecdf342f1193134043966c', id: '22', player: 'Cristiano Rolando', team: 'Juventus'},
{_id: '62ecdf342f1193134043967c', id: '42', player: 'David Beckham', team: 'Real Madrid'},
]
This is the code that I'm using to retrieve the one single entry that matches a specific id and then I'd also like to get the related entries.
export async function getStaticProps({ params }) {
const { db } = await connectToDatabase();
const jerseyA = await db
.collection("Jerseys")
.find({ id: params.jersey })
.sort()
.toArray();
const jersey = JSON.parse(JSON.stringify(jerseyA))[0];
return { props: { jersey } };
}

Now that you know the name, do another fetch like .find({player: jersey.player})

I'm not sure of the output format you want, but here's one way to return all documents that match the "player" name of the given "id".
db.Jerseys.aggregate([
{
"$match": {
// your id goes here
"id": "17"
}
},
{
"$lookup": {
"from": "Jerseys",
"localField": "player",
"foreignField": "player",
"as": "docs"
}
},
{"$unwind": "$docs"},
{"$replaceWith": "$docs"}
])
Example output:
[
{
"_id": "62ecdf342f1193134043965c",
"id": "17",
"player": "Cristiano Rolando",
"team": "Manchester United"
},
{
"_id": "62ecdf342f1193134043966c",
"id": "22",
"player": "Cristiano Rolando",
"team": "Juventus"
}
]
Try it on mongoplayground.net.

Just an addition to #rickhg12hs solution, to ignore the first record. You can use the following query to ignore the first record (where the id also matched) and the others.
db.Jerseys.aggregate([
{
"$match": {
"id": "12"
}
},
{
"$lookup": {
"from": "Jerseys",
"localField": "player",
"foreignField": "player",
"as": "docs"
}
},
{
"$unwind": "$docs"
},
{
"$replaceWith": "$docs"
},
{
"$match": {
"id": {
"$not": {
"$eq": "12"
}
}
}
}
])
A possible javascript translation of it, should be,
export async function getStaticProps({ params }) {
const { db } = await connectToDatabase();
const { jersey: id } = params;
const jerseyA = await db
.collection("Jerseys")
.aggregate([
{
"$match": {
id
}
},
{
"$lookup": {
"from": "Jerseys",
"localField": "player",
"foreignField": "player",
"as": "docs"
}
},
{
"$unwind": "$docs"
},
{
"$replaceWith": "$docs"
},
{
"$match": {
"id": {
"$not": {
"$eq": id
}
}
}
}
]).toArray();
const jersey = JSON.parse(JSON.stringify(jerseyA))[0];
return { props: { jersey } };
}

Related

How to match documents of same collection in a lookup where an array field has the highest number of matching elements?

I have a products collection with a schema as follows:
{
brand: String,
category: String,
title: String,
description: String,
product_variants: [...],
tags: [{label:String},{value:String}],
}
I am performing a lookup in the same collection to add a field consisting of related products for each product. I need to get related products by matching documents that have similar elements in the tags array. So far I have the got the following lookup pipeline:
{
$lookup: {
from: 'products',
let: { "tags": "$tags.label" },
pipeline: [{
$match: {'product_variants.status': {$eq: 'Active'}}
},
{
'$match': {
'$expr': {
'$in': ['$tags.label', '$$tags']
}
},
},
{
$match: { 'product_variants': {
$elemMatch: {
'variant_details': {
$elemMatch: {
'inventory': {
$elemMatch: {
quantity: {$gt:0},
}
}
}
}
}
}}
}, {
$project: {
product_variants: {
"$filter": {
"input": {
"$map": {
"input": "$product_variants",
"as": "variants",
"in": {
"variant_code": "$$variants.variant_code",
"images": {$slice: ["$$variants.images", 1]},
"slug": "$$variants.slug"
}
}
},
"as": "related_products",
"cond":{$gt: [{$size: "$$related_products.images"}, 0]}
}
}
}
}, { $limit: 3 } ],
"as": "related_products"
}
},
I have tried using $all operator but it is not working either.

How to create nested array in realm without key(React Native)

{
"a": [
[
{
"_id": "57e55b64016c3551c025abc1",
"title": "Main Campus"
},
{
"_id": "5810e2e27064497f74ad4874",
"title": "Ahm Campus"
},
{
"_id": "5d5d2633a1d0680620ac3cce",
"title": "Baroda"
},
{
"_id": "5d5d3af3a1d0680620ac3ef8",
"title": "India"
}
],
[
{
"_id": "57e55b64016c3551c025abc1",
"title": "Main Campus"
},
{
"_id": "5810e2e27064497f74ad4874",
"title": "Ahm Campus"
},
{
"_id": "5d5d2633a1d0680620ac3cce",
"title": "Baroda"
},
{
"_id": "5d5d3af3a1d0680620ac3ef8",
"title": "India"
}
]
]
}
How to create the schema in the realm(React native) for this type of JSON object. I tried all possible ways but did not found any specific solution. Basically, it is a nested array where the second array does not have any specific key(I tried with key it works fine but I want to do it without adding key).
You can use something like:
const ParentSchema = {
name: "parent",
properties: {
key: "string",
values: "Value[]"
}
};
const ValueSchema = {
name: "Value",
embedded: true,
properties: {
_id: "string",
title: "string"
}
};
You can insert objects like:
realm.write(() => {
realm.create("Parent", { key: "a", values: [
{ _id: "57e55b64016c3551c025abc1", title: "Main Campus" },
{ _id: "5810e2e27064497f74ad4874", title: "Ahm Campus" }
]
});
});
Documentation: https://docs.mongodb.com/realm/node/data-model
As of now there is no way to insert direct value in Realm database without key so for now we need to modify data and then we can store in following schema.
const ParentSchema = {
name: "parent",
properties: {
a: "level[]"
}
};
const level = {
name: 'level',
properties: {
level: 'sites[]'
}
}
const sites = {
name: 'sites',
properties: {
sites: 'site[]'
}
}
const site = {
name: 'site',
properties: {
title: 'string?',
_id: 'string?',
version: 'int?',
}
}
Data modification need to done like following.
var a = {
level: []
}
data.a.map((Site, index) => {
const sites = []
Site.map((s) => { sites.push(s)})
a.level.push({sites})
})

Query only for numbers in nested array

I am trying to get an average number of an key in a nested array inside a document, but not sure how to accomplish this.
Here is how my document looks like:
{
"_id": {
"$oid": "XXXXXXXXXXXXXXXXX"
},
"data": {
"type": "PlayerRoundData",
"playerId": "XXXXXXXXXXXXX",
"groupId": "XXXXXXXXXXXXXX",
"holeScores": [
{
"type": "RoundHoleData",
"points": 2
},
{
"type": "RoundHoleData",
"points": 13
},
{
"type": "RoundHoleData",
"points": 3
},
{
"type": "RoundHoleData",
"points": 1
},
{
"type": "RoundHoleData",
"points": 21
}
]
}
}
Now, the tricky part of this is that I only want the average of points for holeScores[0] of all documents with this playerid and this groupid.
Actually, the best solution would be collecting all documents with playerid and groupid and create a new array with the average of holeScores[0], holeScores[1], holeScores[2]... But if I only can get one array key at the time, that would be OK to :-)
Here is what I am thinking but not quit sure how to put it together:
var allScores = dbCollection('scores').aggregate(
{$match: {"data.groupId": groupId, "playerId": playerId}},
{$group: {
_id: playerId,
rounds: { $sum: 1 }
result: { $sum: "$data.scoreTotals.points" }
}}
);
Really hoping for help with this issue and thanks in advance :-)
You can use $unwind with includeArrayIndex to get index and then use $group to group by that index
dbCollection('scores').aggregate(
{
$match: { "data.playerId": "XXXXXXXXXXXXX", "data.groupId": "XXXXXXXXXXXXXX" }
},
{
$unwind: {
path: "$data.holeScores",
includeArrayIndex: "index"
}
},
{
$group: {
_id: "$index",
playerId: { $first: "data.playerId" },
avg: { $avg: "$data.holeScores.points" }
}
}
)
You can try below aggregation
db.collection.aggregate(
{ "$match": { "data.groupId": groupId, "data.playerId": playerId }},
{ "$group": {
"_id": null,
"result": {
"$sum": {
"$arrayElemAt": [
"$data.holeScores.points",
0
]
}
}
}}
)

Mongoose - How to retrieve an array of objects from each document in collection?

Each document in my collection looks something like this (JSON):
{
name: "Roger",
matches: [
{
opponent: "Rafael Nadal",
match_date: 1494536400000
},
{
opponent: "Nick Kyrgyos",
match_date: 1494557400000
}
]
}
I want to extract all the matches each player had and also sort them by match_date using Mongoose, but I don't know how.
Could you please help me with this?
You can try below aggregation
db.collection.aggregate([
{ "$unwind": "$matches" },
{ "$sort": { "matches.match_date": 1 }},
{ "$group": {
"_id": "$_id",
"matches": { "$push": "$matches" }
}},
{ "$limit": 20 },
{ "$project": { "matches": 1, "numberOfMatches": { "$size": "$matches" } }}
])

Nodejs Mongoose select a entire document but only with selected items in a property array

I'm new to nodejs and currently i'm developing a Web API using nodejs, express and mongoose. Can anyone help me on following mongoose query.
var EventSchema = new Schema({
event_title: {
type: String,
required: true
},
service_order: [{
_id:{
type: String
},
service : {
type: Schema.Types.ObjectId,
ref: "Service"
}
}]
});
I want to select a entire Event document but only with selected service_order items in that array
ex :-
this is a entire Event document
{
_id: "sample_id",
name: 'some name',
"service_order": [
{
"_id": "1"
"service": {
"_id": "59c005524d9c141fe0d95f15"
},
{
"_id": "2"
"service": {
"_id": "59c005524d9c141fe0d95f18"
},
{
"_id": "3"
"service": {
"_id": "59c005524d9c141fe0d95f18"
},
{
"_id": "4"
"service": {
"_id": "59c005524d9c141fe0d95f18"
}
],
}
But I want to execute a single mongoose query which can give this as the output
{
_id: "sample_id",
name: 'some name',
"service_order": [
{
"_id": "1"
"service": {
"_id": "59c005524d9c141fe0d95f15"
},
{
"_id": "2"
"service": {
"_id": "59c005524d9c141fe0d95f18"
}
],
}
Initially I know the Event id ("sample_id") and the ids of service_orders that i want to select ( ["1","2"] ).
You can use mongodb aggregate to achieve that
don't forget to replace sample_id and ["1" , "2"] with your dynamic data
Check the code below:
db.event.aggregate([
{
$match: { _id: "sample_id" }
},
{
$unwind: { path: "$service_order" }
},
{
$match : { 'service_order._id' : { $in : [ "1" , "2"]} }
},
{
$group : {
_id: { _id: "$_id", "name": "$name"},
service_order: { $addToSet: "$service_order" },
}
},
{
$project : {
_id : "$_id._id",
name : "$_id.name",
service_order : 1
}
}
])

Resources