Update if there is no such element - arrays

I have a document
{
videoSection:{
title: "Social construction",
videos: [
{title: "a", isApproved: true},
{title: "b", isApproved: false},
{title: "c", isApproved: true},
],
isPublished: false
}
}
I need to update the document (to set isPublished: true) if all the isApproved fields of the videos of videoSection is true which means if there is no isApproved = false.
What is the way of doing this ?

Demo - https://mongoplayground.net/p/obReFQ3FmkV
db.collection.update(
{
"videoSection.videos.isApproved": {
$exists: true,
$ne: false
}
},
{ $set: { "videoSection.isPublished": true } },
{ multi: true }
)
Note - { $exists: true } this add extra checks for the case where videos array is empty or not present, update will not happen.

check condition if isApproved is not false then update isPublished to true
db.collection.updateMany({
"videoSection.videos.isApproved": {
$ne: false
}
},
{
$set: {
"videoSection.isPublished": true
}
})
Playground

Related

I am having difficulty accessing this nested array to carry out an update

SCHEMA
Below is my schema structure, kindly correct me if I am getting it wrong. I want to be able to update the ConnectState from false to true using an ObjectId
phones: {
type: String,
required: true,
},
User: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
// required: true,
},
Userpost: {
type: mongoose.Schema.Types.ObjectId,
ref: "userpost",
// required: true,
},
friendshipStatus: [
{
isFriend: {
FProfile: {
type: mongoose.Schema.Types.ObjectId,
ref: "profile",
},
ConnectStatus: {
type: Boolean,
default: false,
},
},
},
],
});
What I have tried
I want to update the Boolean value on ConnectStatus from false to true. I know I am getting the process wrong.
const result = await Profile.updateOne(
{ "friendshipStatus.isFriend.FProfile": uid },
{ $set: { "friendshipStatus.$.isFriend.ConnectStatus": true } },
{ arrayFilters: [{ "friendshipStatus.isFriend.FProfile": uid }] }
);
Try with:
const result = await Profile.update(
{ 'friendshipStatus.isFriend.FProfile': uid },
{ $set: { 'friendshipStatus.$.isFriend.ConnectStatus': true } },
);

How to find and update specific value in nested object array in typescript

I have a nested object array with n level like this:
const data = {
"id": null,
"label": "Locations",
"value": "Locations",
"expanded": true,
"children": [
{
"id": "A978919C-E99C-EB11-8F2E-A01D48E35246",
"value": "Tokyo ",
"label": "Tokyo ",
"checked": true,
"children": [
{
"id": "88887069-179A-EB11-9C25-00163EDCFF95",
"isDefault": true,
"locationId": "A978919C-E99C-EB11-8F2E-A01D48E35246",
"parentsId": null,
"createDate": "2021-06-20T19:03:55.190Z",
"updateDate": "2021-10-16T13:36:41.353Z",
"label": "RAJ - Automotive Japan Fa Fusoh",
"checked": true,
"children": [],
"disabled": false
}
]
},
.
.
]
}
I have an object
{
"id": "A978919C-E99C-EB11-8F2E-A01D48E35246",
"value": "Tokyo ",
"label": "Tokyo ",
"checked": false,
"_depth": 1,
"_id": "A978919C-E99C-EB11-8F2E-A01D48E35246",
"_parent": "rdts1-0",
"_children": [
"88887069-179A-EB11-9C25-00163EDCFF95"
],
"_focused": true
}
and I want to edit checked in the object array by using the IDs in the last object and its children, change each checked in object in the object array to false
I used DFS for the children but I didn't get a good result any help please.
Seems like recursion would suffice:
const data = {
id: null,
label: 'Locations',
value: 'Locations',
expanded: true,
children: [
{
id: 'A978919C-E99C-EB11-8F2E-A01D48E35246',
value: 'Tokyo ',
label: 'Tokyo ',
checked: true,
children: [
{
id: '88887069-179A-EB11-9C25-00163EDCFF95',
isDefault: true,
locationId: 'A978919C-E99C-EB11-8F2E-A01D48E35246',
parentsId: null,
createDate: '2021-06-20T19:03:55.190Z',
updateDate: '2021-10-16T13:36:41.353Z',
label: 'RAJ - Automotive Japan Fa Fusoh',
checked: true,
children: [],
disabled: false,
},
],
},
],
}
function setCheckedToFalse(childrenArr) {
// error handling
if (!Array.isArray(childrenArr)) {
return;
}
childrenArr.forEach((child) => {
// set to false
child.checked = false
// recursion for other children
setCheckedToFalse(child.children)
})
}
setCheckedToFalse(data.children)
console.log(data);
Not sure if I correctly understood the question, but the code below the checked value in the data object is set to false in case it exists in object.
const data = {
id: null,
label: 'Locations',
value: 'Locations',
expanded: true,
children: [
{
id: 'A978919C-E99C-EB11-8F2E-A01D48E35246',
value: 'Tokyo ',
label: 'Tokyo ',
checked: true,
children: [
{
id: '88887069-179A-EB11-9C25-00163EDCFF95',
isDefault: true,
locationId: 'A978919C-E99C-EB11-8F2E-A01D48E35246',
parentsId: null,
createDate: '2021-06-20T19:03:55.190Z',
updateDate: '2021-10-16T13:36:41.353Z',
label: 'RAJ - Automotive Japan Fa Fusoh',
checked: true,
children: [],
disabled: false,
},
],
},
],
};
const object = {
id: 'A978919C-E99C-EB11-8F2E-A01D48E35246',
value: 'Tokyo ',
label: 'Tokyo ',
checked: false,
_depth: 1,
_id: 'A978919C-E99C-EB11-8F2E-A01D48E35246',
_parent: 'rdts1-0',
_children: ['88887069-179A-EB11-9C25-00163EDCFF95'],
_focused: true,
};
// Gets all ids (nested ones included) from object
function getIdsHashMap(obj) {
const idsHashMap = {};
const loopThroughChildren = (children = []) => {
children.forEach((el) => {
idsHashMap[el] = true;
if (el._children) {
loopThroughChildren(el._children);
}
});
};
if (obj.id) {
idsHashMap[obj.id] = true;
}
loopThroughChildren(obj._children);
return idsHashMap;
}
// Sets checked in data to false if an id exists in object
function setCheckedValue(obj) {
const idsHash = getIdsHashMap(object);
const loopThgroughChildren = (children) => {
if (!Array.isArray(children)) {
return;
}
children.forEach((child) => {
// Checks, if id exists in hashmap from object
if (idsHash[child.id]) {
child.checked = false;
}
if (child.children) {
loopThgroughChildren(child.children);
}
});
};
if (obj.children) {
loopThgroughChildren(obj.children);
}
return obj;
}
console.log(setCheckedValue(data));

React Native Array Updates

I have two arrays of objects which have properties that match (id & name).
var result1 = [[
{ title: "Option 1", enable: false },
{ title: "Option 2", enable: false },
{ title: "Option 3", enable: false },
{ title: "Option 4", enable: false },
{ title: "Option 5", enable: false }
]
;
var result2 = [
{ title: "Option 3", enable: false },
{ title: "Option 4", enable: false },
];
result1.map(item => {
const isChecked = result2.some(({ title }) => title === item.title);
return {
...item,
checked: isChecked
}
});
Use the following code,
import _ from 'lodash';
this.setState({
result1: this.state.result1.map(item => {
return (_.find(this.state.result2, item)) ? { ...itemObj, checked: true }: { ...itemObj, checked: false }; });
// return (_.find(this.state.result2, {'title': item.title})) ? { ...itemObj, checked: true }: { ...itemObj, checked: false }; }); // if you want to check only title
});
lodash is a lib which will be helpful in such things.
Detailed documentation for the same can be found in this link, for find.
The above code with check the whole item object if you want to check only part of it say only title below is the code

Looping nested array Object in ListView React native

I currently trying to play around with react-native..
I want to make a list view that get the dataSource from var which contain an object that have nested array inside.
var questionArray = [
{
question: "What is the emotion of the user? choose all that apply!",
answerArray: [
{ name: "Cheerful", status: true, answered: false },
{ name: "Impulsive", status: false, answered: false },
{ name: "Firm", status: false, answered: false },
{ name: "Merry", status: true, answered: false },
{ name: "Jumpy", status: false, answered: false },
{ name: "Energetic", status: false, answered: false },
{ name: "Glowing", status: false, answered: false },
{ name: "Animated", status: false, answered: false },
{ name: "Lively", status: false, answered: false },
{ name: "Creepy", status: false, answered: false },
{ name: "Excited", status: true, answered: false },
{ name: "Tense", status: false, answered: false },
{ name: "Unrestful", status: false, answered: false },
{ name: "Pleased", status: true, answered: false },
{ name: "Unrestful", status: false, answered: false },
{ name: "Hasty", status: false, answered: false },
{ name: "Delighted", status: true, answered: false },
{ name: "Hedonistic", status: false, answered: false },
{ name: "Eager", status: false, answered: false },
{ name: "Joyful", status: false, answered: false },
]
},
{
question: "What is the best way to describe this person's character? Choose all that apply.",
answerArray: [
{ name: "Cheerful", status: true, answered: false },
{ name: "Impulsive", status: false, answered: false },
{ name: "Firm", status: false, answered: false },
{ name: "Merry", status: true, answered: false },
{ name: "Jumpy", status: false, answered: false },
{ name: "Energetic", status: false, answered: false },
{ name: "Glowing", status: false, answered: false },
{ name: "Animated", status: false, answered: false },
{ name: "Lively", status: false, answered: false },
{ name: "Creepy", status: false, answered: false },
{ name: "Excited", status: true, answered: false },
{ name: "Tense", status: false, answered: false },
{ name: "Unrestful", status: false, answered: false },
{ name: "Pleased", status: true, answered: false },
{ name: "Unrestful", status: false, answered: false },
{ name: "Hasty", status: false, answered: false },
{ name: "Delighted", status: true, answered: false },
{ name: "Hedonistic", status: false, answered: false },
{ name: "Eager", status: false, answered: false },
{ name: "Joyful", status: false, answered: false },
]
}
];
and I called this variable inside render ListView which trigger renderRow function..
_renderRow( rowData, sectionID, rowID ) {
return (
<View>
<Text>{rowData.question}</Text>
<Text>{rowData.answerArray[0].name}</Text>
</View>
);
}
render() {
return (
<View>
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
/>
</View>
);
}
How do I render the loop inside this listView ?
Even the when I hard coded the index like above code, it's not working..
Thank you.
You should make two separate Components: Question & Answer
I've made a Codepen for you as an example, using your data
At first, I pass the questionsArray as prop to the ListView Component:
class Application extends React.Component {
render() {
return (
<div>
{ questionsArray.map((question, key) => <ListView key={`listview-${key}`} question={question} />) }
</div>
);
}
}
Then, you can pass the answers to the ListViewItem Component, like this:
class ListView extends React.Component {
render() {
return (
<div>
{this.props.question.question}
{this.props.question.answerArray.map((answer, key) => <ListViewItem answer={answer} />)}
</div>
);
}
}
This is the ListViewItem:
class ListViewItem extends React.Component {
render() {
return (
<div>
{this.props.answer.name}
</div>
);
}
}

MongoDB $addToSet replace

I have a document like the following one:
{
_id: "00112233",
array: [
{
_id: "potatoes",
amount: 5
},
{
_id: "carrots",
amount: 6
}
]
}
and I need to update or push the documents so that if there is one in the array, it gets replaced, if not, it gets pushed.
If i try to do an update like this:
db.collection.update(
{ _id: "00112233" },
{
"$push": { "array": { "$each": [
{
_id: "potatoes",
amount: 6
},
{
_id: "apples",
amount: 2
}
]}}
}
)
In the database I will find two "potatoes" field. But if I try to replace the "push" with a "addToSet" I won't have the "potatoes" field updated.
Is there any way I can do this in only one query?
Unfortunately, you can't achieve the result that you are expecting in single update operation.
The addToSet doesn't work for this scenario because the array has embedded documents. addToSet checks for both the attribute names and values whether it matches. If match is found, it does nothing. If the match is not found, it adds the data to the array attribute.
In the above case for "potatoes", the amount value of potatoes doesn't match. So it inserts a new element into array. So the result has two potatoes with 2 different values.
{
_id: "potatoes",
amount: 6
}
You may need to perform two update operations.
1) Update the value of an array field if it exists using $set
db.collection.update(
{ _id: "00112233", "array._id": "potatoes"},
{
"$set": { "array.$":
{
_id: "potatoes",
amount: 7
}
},
}
);
2) Add the new element to an array field if it doesn't exists using $addToSet
db.collection.update(
{ _id: "00112233"},
{
"$addToSet": { "array":
{
_id: "apples",
amount: 7
}
},
}
);
you need to use $set instead of $push/$addToSet.
https://docs.mongodb.com/manual/reference/operator/update/set/
Had a similar issue and tried notion quest's approach and it did work.My schema was as follows
const MatchInstanceSchema = new Schema({
_id: false,
pseudoKey: { type: String, required: true, unique: true },
service: { type: String, required: true },
region: { type: String, required: true },
team1: {
name: { type: String, required: true },
price: { type: String, required: true }
},
team2: {
name: { type: String, required: true },
price: { type: String, required: true }
},
drawPrice: { type: String, required: true },
url: { type: String, required: true }
})
const MatchSchema = new Schema({
pseudoKey: { type: String, required: true, unique: true },
sport: { type: String, required: true },
league: { type: String, required: true },
date: { type: Date, required: true },
team1: { type: String, required: true },
team2: { type: String, required: true },
matchInstances: [MatchInstanceSchema]
})
I wanted to update the following matchInstances subdocument if there exists a match whose pseudoKey was same as the top level(parent document) pseudoKey without
duplicating the value and create a new entry in the matchInstances subdocument if it did not exist.
{
"_id" : ObjectId("5b47d47e7fd01d29178aa3a5"),
"pseudoKey" : "newcastle-tottenham",
"sport" : "Soccer",
"league" : "Premier League",
"date" : ISODate("2018-08-11T11:30:00.000Z"),
"team1" : "Newcastle",
"team2" : "Tottenham",
"matchInstances" : [
{
"team1" : {
"name" : "Newcastle",
"price" : "74.6"
},
"team2" : {
"name" : "Tottenham",
"price" : "2.06"
},
"pseudoKey" : "newcastle-tottenham",
"service" : "Betin",
"region" : "Kenya",
"drawPrice" : "3.45",
"url" : "https://web.betin.co.ke/Sport/SubEventOdds.aspx?SubEventID=16701401"
}
]
This was my solution
//If it already exists we just want to update with the new values without
//duplicating
Match.findOneAndUpdate(
{ pseudoKey: pseudoKey, "matchInstances.service": service },
{ $set: { "matchInstances.$": matchInstances[0] } }
//If it does not exist we want to add it as a new entry into the matchInstances
//subdocument
Match.findOneAndUpdate(
{ pseudoKey: pseudoKey },
{ $addToSet: { matchInstances: matchInstances } }
)

Resources