MongooseJS trying to populate using nested query operator - javascript

I have a code:
const profiles = await Profile.find({ profileVisibility: true })
.populate("products", null, {
itemName: "Item 1"
});
This works because I am trying to find itemName which is direct field of the Profile.
However, in the same Profile Schema I have nested object named lists which is a object with nested fields example:
ProfileSchema = {
itemName: "Item 1",
lists: {
name: "name 1",
price: "price 1"
}
}
When I try to do this I get null (this happens every time I try to query nested properties):
.populate("list", null, {
lists: {name: { $eq: 'name 1' } }
}

Related

Mongodb find documents with given field value inside an array and its id in another array inside the same document

My data model:
{
_id: ObjectId,
persons:[{
_id: ObjectId,
name: String,
...
}],
relations: [{
type: String,
personId: ObjectId,
...
}],
...
}
Here's my issue:
I am trying to find documents where person's name is x and it's _id is inside the relations array (personId) with a given type.
Example:
My data:
[{
_id:"1",
persons:[{
_id:"1",
name: "Homer"
},
{
_id:"2",
name: "Bart"
}],
relations: [{
type:"House_Owner",
personId: 1,
}],
}]
Request_1:
Find all documents where "Homer" is the house owner
Result:
[{
_id:"1",
...
}]
Request_2:
Find all documents where "Bart" is the house owner
Result:
[]
Any help would be appreciated.
The only solution I see here is to do the find operation with the given name value and after that filter the mongodb result.
PS: I cannot change the existing data model
EDIT:
I found a solution to do this by using $where operator with a javascript function but I am not sure that's the most efficient way.
db.myCollection("x").find({
$where: function() {
for (const relation of this.relations) {
if(relation.type === "House_Owner") {
for (const person of this.persons) {
if(person.name === "Homer" && person._id.equals(relation.personId)) {
return true;
}
}
}
}
}
})
You can do something like this:
const requiredName="x"
const requiredId = "id"
await yourModel.find({$and:[{"relations.personId":requiredId },{"persons.name":requiredName}]})

How do I update selected values in react multiselect

I have a modal in which I edit my model. In my form, I also have a multi-select tag field. The "tags" is an array of objects with labels and values as show below.
There is a dummy tags object (mimicking a database) which all the tags are selected from.
const dummyTags = [
{ label: "Test 1", value: "Test 1" },
{ label: "Test 2", value: "Test 2" },
{ label: "Test 3", value: "Test 3" },
];
So, if I selected "Test 1" and "Test 2", my tags array becomes (only the values are then saved in the database):
const tgs = [
{
label: "Test 1",
value: "Test 1"
},
{
label: "Test 2",
value: "Test 2"
}
];
However, during update, the tags come from the database as ['Test 1','Test 2'].
I want to use the tags from the database shown in the line above to compare the dummyTags array so I can have a new array of objects with values like the tgs array above.
At the moment, this is what I am doing:
let newtags = [];
if (groupTags.length > 0) { //groupTags is the tags from the database
groupTags?.forEach((tag) => {
newtags.push({ label: tag, value: tag });
});
}
This works, but I think it's not reliable. What if the label and value are not the same for a particular tag?
Is there a better way of implementing this?
const arr = ['Test 1','Test 2', 'Test 3']
const result = arr.map(d => ({label: d, value: d}));
console.log(result)

Returning the ids from the object within the arrays

I have a multidimensional javascript array of objects that I am trying to use to simply collate the Unit id into a new array as shown below.
What is the best solution for returning the id within the inner value so I just get an array of the ids whatever I try seems to not work
[
{
units: [
{
id: 10000282,
name: "Group 1",
},
{
id: 10000340,
name: "Group 2",
},
{
id: 10000341,
name: "Group 3",
},
],
},
{
units: [
{
id: 10000334,
name: "Group 4",
},
],
},
]
Expected output - just return an array with simply the ids
e.g
ids = [ 10000282, 10000340, 10000341, 10000334 ]
Assuming that data is in variable data:
> data.map(o => o.units.map(u => u.id)).flat()
[ 10000282, 10000340, 10000341, 10000334 ]
This assumes you're in an environment where .flat() is a thing.
If that's not the case, the longer way around is
const ids = [];
data.forEach(o => {
o.units.forEach(u => {
ids.push(u.id);
});
});

How to filter an object array based on the contents of child array?

I have this data
var data = [
{
title: "App development summary",
category: [],
},
{
title: "to experiment 2",
category: [],
},
{
title: "Some of these books I have read",
category: [
{
_id: "5f7c99faab20d14196f2062e",
name: "books",
},
{
_id: "5f7c99faab20d14196f2062f",
name: "to read",
},
],
},
{
title: "Quora users and snippets",
category: [
{
_id: "5f7c99feab20d14196f20631",
name: "quora",
},
],
},
{
title: "Politics to research",
category: [
{
_id: "5f7c9a02ab20d14196f20633",
name: "politics",
},
],
},
];
Say I want to get all the entries with the category of books. I tried doing this:
var bookCat = data.map(note => {
return note.category.map(cat => {
if(cat.name === "books" ) return note
})
})
But the result comes back with some empty and undefined arrays.
I was able to filter the empty arrays (at one point) but not the undefined
Edit
In plain English "if the object ha category.name "books", give me the title"
Filter by whether the array's category contains at least one name which is books:
var data=[{title:"App development summary",category:[]},{title:"to experiment 2",category:[]},{title:"Some of these books I have read",category:[{_id:"5f7c99faab20d14196f2062e",name:"books"},{_id:"5f7c99faab20d14196f2062f",name:"to read"}]},{title:"Quora users and snippets",category:[{_id:"5f7c99feab20d14196f20631",name:"quora"}]},{title:"Politics to research",category:[{_id:"5f7c9a02ab20d14196f20633",name:"politics"}]}];
const output = data
.filter(item => item.category.some(
({ name }) => name === 'books'
));
console.log(output);
If there's guaranteed to be only a single matching object, use .find instead:
var data=[{title:"App development summary",category:[]},{title:"to experiment 2",category:[]},{title:"Some of these books I have read",category:[{_id:"5f7c99faab20d14196f2062e",name:"books"},{_id:"5f7c99faab20d14196f2062f",name:"to read"}]},{title:"Quora users and snippets",category:[{_id:"5f7c99feab20d14196f20631",name:"quora"}]},{title:"Politics to research",category:[{_id:"5f7c9a02ab20d14196f20633",name:"politics"}]}];
const output = data
.find(item => item.category.some(
({ name }) => name === 'books'
));
console.log(output);

JavaScript | Spread operator update nested value

I am trying to update a nested value of an object using the spread operator. This is my first time using this and I believe I am pretty close to achieving my end goal but I just can't seem to figure out what I actually need to do next.
I have an array which is structured like this:
[
{
name: "Category 1",
posts: [
{
id: 1,
published: false,
category: "Category 1"
},
{
id: 2,
published: true,
category: "Category 1"
}
]
},
{
name: "Category 2",
posts: [
{
id: 3,
published: true,
category: "Category 2"
},
{
id: 4,
published: true,
category: "Category 2"
}
]
}
]
On the click of a button I am trying to update the published value, and as I am using React I need to set the state. So it got recommended to me that I update using the spread operator.
onPostClick(post) {
post.pubished = !post.published;
this.setState({...this.state.posts[post.category], post})
}
If I log out the result of {...this.state.posts[post.category], post} I can see that the published is getting added to the parent which forms:
{
name: "Category 1",
published: false,
posts: [
...
]
}
Obviously this isn't the intended result, I want it to update the actual object within the posts object.
I have tried to do something like this.setState({...this.state.posts[post.category].posts, post}) but I get a message that it is undefined.
You can't access your data with this.state.posts[post.category]. posts data in the objects of the array.
You can make a filter to find your category object in array and change its posts value.
onPostClick(post) {
//CLONE YOUR DATA
var postArray = this.state.posts;
//FIND YOUR CATEGORY OBJECT IN ARRAY
var categoryIndex = postArray.findIndex(function(obj){
return obj.name === post.category;
});
//FIND YOUR POST AND CHANGE PUBLISHED VALUE
postArray[categoryIndex].posts.forEach(function(item){
if (item.id === post.id) {
item.published = !item.published;
}
});
//SET TO STATE TO RERENDER
this.setState({ posts: postArray});
}
This should work if your name of the state is true.
just adding, we know there are many ways to succeed, maybe you also want to try this way too..
onPostClick = post => {
let published = this.state.data.map((item, i) => {
item.posts.map((item_post, i) => {
if (item_post.category === post.category) {
item_post.published = !post.published;
}
});
});
this.setState({ ...this.state.data, published });
};

Categories

Resources