Querying a many to many relationship based on a value - node.js

Currently I have a many-to-many relationship between entities. A Transaction contains many persons and a Person contains many Transactions. I'm writing a query to filter out transactions so that the transactions contains the person's name. The problem I'm running into is when I filter based on name, it removes the other Person from the transaction.
Example:
{
"id": 1,
"txnDate": "2021-03-09T12:40:26.000Z",
"persons": [
{
"id": 1,
"name": "Bill"
},
{
"id": 2,
"name": "Jen"
}
]
},
{
"id": 2,
"txnDate": "2021-03-09T12:40:26.000Z",
"persons": [
{
"id": 2,
"name": "Jen"
},
{
"id": 3,
"name": "Bob"
}
]
},
My current query is:
query.leftJoinAndSelect('transaction.persons', 'persons')
.andWhere('persons.name = :name', { name });
where name is a string. If I set name= Bill it results in:
{
"id": 1,
"txnDate": "2021-03-09T12:40:26.000Z",
"persons": [
{
"id": 1,
"name": "Bill"
},
]
},
However, I want it so that when I query by name it would result in:
{
"id": 1,
"txnDate": "2021-03-09T12:40:26.000Z",
"persons": [
{
"id": 1,
"name": "Bill"
},
{
"id": 2,
"name": "Jen"
}
]
},
I'm really stuck and I would love any ideas on how to solve this
Current Stack: Nodejs, TypeORM, TypeScript

Related

is there any mongo db query to only add new elements the nested elements by id

my data structure is and products elements all tags in empty
I need to add a value to mongo db inner object with array element without looking at other value. Can some one advice to do this.
[
{
"item": "journal",
"id": 11,
"products": [
{
"id": 3,
"name": "p one",
"tags": []
}
]
},
{
"item": "notebook",
"id": 14,
"products": [
{
"id": 4010,
"name": "item-five",
"tags": []
}
]
}
]
and I want to add tag in products elements with match product id '4010', so the expected response should be like
[
{
"item": "journal",
"id": 11,
"products": [
{
"id": 3,
"name": "p one",
"tags": []
}
]
},
{
"item": "notebook",
"id": 14,
"products": [
{
"id": 4010,
"name": "item-five",
"tags": [
{
"id": 21,
"key": "tag-one",
"name": "tag-one",
}
]
}
]
}
]
You should look at arrayFilter option https://www.mongodb.com/docs/v6.0/reference/operator/update/positional-filtered/#update-all-documents-that-match-arrayfilters-in-an-array
Something like this might do the trick.
db.collection.updateMany(
{ },
{ $push: { "products.$[x].tags": {
"id": 21,
"key": "tag-one",
"name": "tag-one",
} } },
{ arrayFilters: [{ "x.id": 4010 }] }
);

Nodejs mongoose : how to retreive data from db collection related to other collection

I want to implement a function that would process students, courses and instructors data (loaded from MongoDB collections) in order to produce information about students enrolled on courses (and store it in another MongoDB collection). the function reports each student’s:
primary key
their name
the number of courses they are enrolled in
I want to Store the output of this routine in a MongoDB collection called coursereport like this :
[
{
"_id": "jeff",
"value": {
"name": "Jeff Holland",
"numbercourses": 2
}
},
{
"_id": "john.shore",
"value": {
"name": "John Shore",
"numbercourses": 2
}
},
{
"_id": "lee2331",
"value": {
"name": "Lee Aldwell",
"numbercourses": 1
}
},
{
"_id": "rcotter",
"value": {
"name": "Ray Cotter",
"numbercourses": 2
}
},
{
"_id": "scott",
"value": {
"name": "Scott Mills",
"numbercourses": 3
}
}
]
my data :
{
"students": [
{
"_id": "john.shore",
"name": {"first": "John", "last": "Shore"},
"email": "john.shore#gmail.com",
"major": "Electrical Engineering"
},
{
"_id": "jeff",
"name": {"first": "Jeff", "last": "Holland"},
"email": "jeff#yahoo.com",
"major": "Business"
},
{
"_id": "scott",
"name": {"first": "Scott", "last": "Mills"},
"email": "scott#hotmail.com",
"major": "Humanities/Art"
},
{
"_id": "rcotter",
"name": {"first": "Ray", "last": "Cotter"},
"email": "rcotter#msn.com",
"major": "Computer Science"
},
{
"_id": "lee2331",
"name": {"first": "Lee", "last": "Aldwell"},
"email": "lee2331#aol.com",
"major": "Graphic Design"
}
],
"courses": [
{
"_id": "HIST-1010",
"name": "History of the World 1010",
"description": "A bunch of really interesting things that actually happened",
"students": ["scott", "john.shore"],
"ratings": [3, 5, 4, 5, 4, 4, 2, 4]
},
{
"_id": "ENGCOMP-1010",
"name": "English Composition 1010",
"description": "If you can't write well, you've got nothing!",
"students": ["scott", "lee2331", "rcotter", "john.shore", "jeff"],
"ratings": [4, 4, 5, 4, 5, 1, 5]
},
{
"_id": "ART-1050",
"name": "Artistic Interpretation 1050",
"description": "Discover your inner beholder",
"students": ["rcotter", "scott", "jeff"],
"ratings": [3, 4, 3, 4, 4, 3, 4, 4]
}
],
"instructors": [
{
"_id": "wally.r.binns",
"name": {"first": "Wally", "middle": "r", "last": "Binns"},
"email": "wally.r.binns#ssu.edu",
"bio": "I was born in the middle of my mother's doctoral dissertation on Faraday Cage isolation. I've been an academic ever since...",
"publications": [{
"title": "Inverted Celestial Poetry",
"source": "http://www.pubcentral.com/poetry/inverted-celestial-poetry"
}],
"courses": ["ENGLIT-2500"]
},
{
"_id": "gerald.waterford.iii",
"name": {"first": "Gerald", "last": "Waterford", "suffix": "III"},
"email": "gerald.waterford.iii#ssu.edu",
"bio": "My father's father was a great man. My father, not so much. I am restoring the family honor.",
"publications": [{
"title": "Grow, grow, little Dandelion",
"source": "http://www.hopefulstories.com/my-dandelion"
}, {"title": "The teapot and the spoon", "source": "http://www.dishsoap.com/teapot-spoon"}],
"courses": ["ENGCOMP-1010", "HIST-1010"]
},
{
"_id": "kim.b",
"name": {"prefix": "Mrs.", "first": "Kim", "last": "Binnley"},
"email": "kim.b#ssu.edu",
"bio": "My mother told me 'Don't let those dopes push you around'. My life has been a constant struggle against dopeness ever since. Sigh...",
"publications": [],
"courses": ["ART-1050"]
}
]
}
I started with that :
async function produceReport(db, callback) {
const students = db.collection('students');
const courses = db.collection('courses');
const instructors = db.collection('instructors');
// implement missing code that will create 'coursereport' mongo collection with student courses data
callback();
}
module.exports = produceReport;
can any one give a help please
You have to use $lookup
Defined as:
To perform an equality match between a field from the input documents with a field from the documents of the “joined” collection,
So you have to join students and courses and later the output value with instructors..
Take a look at this query:
db.students.aggregate([
{
$lookup: {
from: "courses",
localField: "item",
foreignField: "email",
as: "students_courses"
}
},
{
"$lookup": {
"from": "instructors",
"localField": "students_courses._id",
"foreignField": "courses",
"as": "students_courses"
}
},
{
"$set": {
"_id": "$_id",
"value": {
"name": {
"$concat": [
"$name.first",
" ",
"$name.last"
]
},
"numbercourses": {
"$size": "$students_courses"
}
}
}
},
{
"$project": {
"_id": 1,
"value": 1
}
}
])
First stage is a joing with two collections with the fields indicated and soterd into a field called students_courses.
Then, another join with the _ids from the students_courses.
With the data then you can create a field named value with the name and count the number of courses in other field.
And $project to show only fields you want.
Check an example here
db.students.aggregate([
{
$lookup: {
from: "courses",
localField: "_id",
foreignField: "students",
as: "students_courses"
}
},
{
$project: {
_id: 1,
value: {
name: {
$concat: [
"$name.first",
" ",
"$name.last"
]
},
numbercourses: {
"$size": "$students_courses"
}
}
}
}
])

How can I update one document at nested array

{
"_id": "5e28b029a0c8263a8a56980a",
"name": "Recruiter",
"data": [
{
"_id": "5e28b0980f89ba3c0782828f",
"targetLink": "https://www.linkedin.com/in/dan-kelsall-7aa0926b/",
"name": "Dan Kelsall",
"headline": "Content Marketing & Copywriting",
"actions": [
{
"result": 1,
"name": "VISIT"
},
{
"result": 1,
"name": "FOLLOW"
}
]
},
{
"_id": "5e28b0980f89ba3c078283426f",
"targetLink": "https://www.linkedin.com/in/56wergwer/",
"name": "56wergwer",
"headline": "asdgawehethre",
"actions": [
{
"result": 1,
"name": "VISIT"
}
]
}
]
}
Here is one of my mongodb document. I'd like to update data->actions->result
So this is what I've done
Campaign.updateOne({
'data.targetLink': "https://www.linkedin.com/in/dan-kelsall-7aa0926b/",
'data.actions.name': "Follow"
}, {$set: {'data.$.actions.result': 0}})
But it seems not updating anything and even it can't find the document by this 'data.actions.name'
You need the positional filtered operator since the regular positional operator ($) can only be used for one level of nested arrays:
Campaign.updateOne(
{ "_id": "5e28b029a0c8263a8a56980a", "data.targetLink": "https://www.linkedin.com/in/dan-kelsall-7aa0926b/" },
{ $set: { "data.$.actions.$[action].result": 0 } },
{ arrayFilters: [ { "action.name": "Follow" } ] }
)

Filter XPath to get list and leave out multiple properties with same property name

Through a XMLImport function in Excel I retrieve a JSON set of data. I would like to retrieve a list of ONLY all the names of the pools (in Example below, only 'Men Singles A' and 'Men Singles B').
Because the array of data has different properties called /name I do not know a way to filter out all the /name properties that are part of the /teams property.
[
{
"poolId": 864,
"position": 0,
"name": "Men Singles A",
"totTeams": 7,
"nrPlayersInTeam": 1,
"teams": {
"6453": {
"id": 6453,
"name": "Peter",
{
"id": 3886,
"name": "Peter",
}
]
},
"6501": {
"id": 6501,
"name": "Jack",
"players": [
{
"id": 3912,
"name": "Jack",
}
]
},
}
},
{
"poolId": 865,
"position": 1,
"name": "Men Singles B",
"totTeams": 22,
"nrPlayersInTeam": 1,
"teams": {
"6406": {
"id": 6406,
"name": "John",
"players": [
{
"id": 3844,
"name": "John",
}
]
},
"6408": {
"id": 6408,
"name": "Matthew",
"players": [
{
"id": 3845,
"name": "Matthew",
}
]
},
}
}
]
When trying the following ImportXML function with a Xpath selection, I get a list of all the /name/ properties found in the JSON array.
=IMPORTXML("https://www.tournia.net/api/v2/test/pools?tournamentUrl=test&_format=xml";"//name")
Retrieved List:
Men Singles A
Peter
Peter
Jack
Jack
Men Singles B
John
John
Mtthew
Matthew
What would be the appropriate XPath code to only get a list of all the pool names?

Query to retrieve every subdocument alone without passing parent id using Mongoose

Here i like to explain my problem.
How can i write a mongoose query to retrieve every subdocument from JSON without passing parent_id.
[
{
"_id": "56a320003fe17cc7363dd0d7",
"name": "Leanna Jacobson",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Riley Case"
},
{
"id": 1,
"name": "Herman Carter"
},
{
"id": 2,
"name": "Pacheco Woodard"
}
]
},
{
"_id": "56a3200001501cfa1ea2641d",
"name": "Juliana Bonner",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Keller Woodward"
},
{
"id": 1,
"name": "Fern Knight"
},
{
"id": 2,
"name": "Cain Richards"
}
]
},
{
"_id": "56a3200006864c78ecb1aeed",
"name": "Gena Stark",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Kate Franco"
},
{
"id": 1,
"name": "Araceli Mcclure"
},
{
"id": 2,
"name": "Molly Nelson"
}
]
},
{
"_id": "56a320006d868155161038b6",
"name": "Eve Gonzalez",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Pam Lang"
},
{
"id": 1,
"name": "Christy Marks"
},
{
"id": 2,
"name": "Donovan Warren"
}
]
},
{
"_id": "56a3200066b94852f5680568",
"name": "Coleman Wooten",
"gender": "male",
"friends": [
{
"id": 0,
"name": "Roberta Olson"
},
{
"id": 1,
"name": "Roseann Reid"
},
{
"id": 2,
"name": "Kerri Russell"
}
]
}
]
Here i need to retrieve every friends details from the subdocument array friends for every parent.
so how can i write query for this?????
Suppose the name of your schema is Person, try this one.
//find all document, only select `friends` field from every document
Person.find({}, 'friends', function (err, friends) {
// the return friends is the [[friends], [friends], ...]
});

Resources