Convert the mongoose find() query result into flat array - mongodb

Upon the mongoose find() query the result i am getting is:
[
{
"services":[
{
"location":[
17.4374614,
78.4482878
]
},
{
"location":[
17.4020637,
78.48400519999996
]
},
{
"location":[
17.387031788259197,
78.47838450137715
]
}
]
}
]
Is there any way to extract the output in such a way that i want an array of only location values such as:-
[
'17.4374614',
'78.4482878',
'17.4020637',
'78.48400519999996',
'17.387031788259197',
'78.47838450137715'
]
Edit: I am aware that map method does the job, but i am not able to find a workaround of implementing the map method for the above query.
My schema:
var serviceSchema = new mongoose.Schema({
location:[{type: Number}]
})

I used for-of loop and map function to achieve the result you need
var your_output =[
{
"services":[
{
"location":[
17.4374614,
78.4482878
]
},
{
"location":[
17.4020637,
78.48400519999996
]
},
{
"location":[
17.387031788259197,
78.47838450137715
]
}
]
}
]
var location_array = []
for (var services of output[0].services) {
for(var loc of services.location){
location_array.push(loc)
}
}
location_array.map(String)

Related

MongoDB: Can't update in nested arrays

I've been trying to modify a value in multiple arrays for a few arrays and I can't find documentation on how to do this.
My collection looks like this
"rates": [
{
"category": "Web",
"seniorityRates": [
{
"seniority": "junior",
"rate": 100
},
{
"seniority": "intermediate",
"rate": 135
},
{
"seniority": "senior",
"rate": 165
}
]
}
]
I'm just trying to modify "junior" to "beginner", this should be simple.
Thanks to these answers:
How can I update a multi level nested array in MongoDB?
MongoDB updating fields in nested array
I've manage to write that python code (pymongo), but it doesn't works...
result = my_coll.update_many({},
{
"$set":
{
"rates.$[].seniorityRates.$[j].seniority" : new
}
},
upsert=False,
array_filters= [
{
"j.seniority": old
}
]
)
The path 'rates' must exist in the document in order to apply array updates.
It correspond to this command that doesn't work either
db.projects.updateMany({},
{
$set:
{
"rates.$[].seniorityRates.$[j].seniority" : "debutant"
}
},
{ arrayFilters = [
{
"j.seniority": "junior"
}
]
}
)
clone(t={}){const r=t.loc||{};return e({loc:new Position("line"in r?r.line:this.loc.line,"column"in r?r.column:......)} could not be cloned
What am I doing wrong ?
Any help would be very appreciated
The other option could be Sample
db.collection.update({},
{
$set: {
"rates.$[].seniorityRates.$[j].seniority": "debutant"
}
},
{
arrayFilters: [
{
"j.rate": { //As per your data, you can apply the condition o rate field to modify the level
$lte: 100
}
}
]
})
Or
The actual query should work Sample
db.collection.update({},
{
$set: {
"rates.$[].seniorityRates.$[j].seniority": "debutant"
}
},
{
arrayFilters: [
{
"j.seniority": "junior"
}
]
})
The same should work in python, a sample question
So I was just dumb here, I inverted two parameters so I didn't have the correct collection in the python code...
Thanks Gibbs for pointing out where the mistake was in the mongo command.
I will not delete this post as it can help other to know how to do this kind of queries.

How do I convert an array of objects / subdocuments to an array of strings in a MongoDB Aggregation pipeline?

I have documents with the following structure
{
"_id":{"$oid":"..."},
"work_type": "ASSIGNMENT",
"materials": [
{
"driveFile": {
"driveFile": {
"id": "...",
"title": "filename",
"alternateLink": "https://drive.google.com/...",
"thumbnailUrl": "https://drive.google.com/..."
},
"shareMode": "STUDENT_COPY"
}
},
{
"youtubeVideo": {
"id": "tfdbq",
"alternateLink": "https://www.youtube.com/watch?v=..."
}
}
]
}
And I want to convert the objects in the array to JSON strings so that I can import the materials field as a repeated string column in SQL
Resulting in:
{
"_id":{"$oid":"..."},
"work_type": "ASSIGNMENT",
"materials": [
"{\"driveFile\":{\"driveFile\":{\"id\":\"...\",\"title\":\"filename\",\"alternateLink\":\"https://drive.google.com/...\",\"thumbnailUrl\":\"https://drive.google.com/...\"},\"shareMode\":\"COPY"}}",
"{\"youtubeVideo\":{\"id\":\"tfdbq\",\"alternateLink\":\"https://www.youtube.com/watch?v=...\"}}""
]
}
I am not sure is there any easy option do this, you can try $function operator starting from MongoDB v4.4, indirectly it is JavaScript code,
using aggregate()
{
$set: {
materials: {
$function: {
body: function(materials) {
let m = [];
for (let i = 0; i < materials.length; i++)
m.push(JSON.stringify(materials[i]));
return m;
},
args: ["$materials"],
lang: "js"
}
}
}
}
Playground
using update with aggregation pipeline starting from MongoDB v4.2
Playground

not able to fetch using $and in mongo db

I'm trying to use $and in mongodb stitch function to get data using 2 different condition
data = col.find( { $and: [ { "title": { title } }, { "address.countryName": { country } } ] } ).toArray;
but this shows $undefined:true in response.
please guide what is wrong in here
You need to remove {} in the condition's value
db.getCollection('test').find({
$and: [
{
"title": 'title' --> Here
},
{
"address.countryName": 'country' --> Here
}
]
})

How to toggle an element in array in mongoDB

I have an array of string (ObjectIds) in mongoDB.
I want to toggle an element in that array: If that element exists in the array, remove it, otherwise push that element.
Example:
arr = ["5b608c0769698c3990c64ef3","5b608c0769698c3990c64ef4"]
element = ["5b608c0769698c3990c64ef3"]
Final array:
arr = ["5b608c0769698c3990c64ef4"]
My use-case:
I am creating a blog website and in the Blog Schema I am storing the id of each user who has liked that blog, so that I can highlight the like button when blog is shown to the user.
If you are updating the document, you can use the pipeline within the update. But this feature is available with MongoDB version 4.2 or later.
db.collection.update(
{ },
[
{
$set: {
arr: {
$cond: [ { $in: [ element, "$arr" ] },
{ $setDifference: [ "$arr", [ element ] ] },
{ $concatArrays: [ "$arr", [ element ] ] }
]
}
}
}
]
)
NOTE: Assuming the variable element is a string value.
If you are just querying you can use the following aggregation:
db.collection.aggregate([
{
$addFields: {
arr: {
$cond: [ { $in: [ element, "$arr" ] },
{ $setDifference: [ "$arr", [ element ] ] },
{ $concatArrays: [ "$arr", [ element ] ] }
]
}
}
}
] )
But, if you are using MongoDB version earlier than 4.2, then you can use the aggregate output from above to update the document:
db.collection.aggregate( [
// aggregation pipeine from above ...
] ).forEach( doc => db.collection.updateOne( { _id: doc._id }, { $set: { arr: doc.arr } } ) )
Its maybe not the best solution, but a easy one. You can add your element to the array with $addToSet and check with nModified if you modified the array. 0 means it already exist, and 1 mean you added new Element to it.
So you use mongoose as you said then you have a Model lets say Post. I dont know witch backend langauge you use, but i will show it with node.js here:
let result = await Post.updateOne({ _id: "someId" }, {
$addToSet: {
arr: element
}
})
if(result.nModified === 0){
//0 means, no modifikation, that means its already liked
await Post.updateOne({ _id: "someId" }, {
$pull: {
arr: element
}
})
}
response.send("Done");

Find returns object on child element

I'm trying to find all the fruit in my database where the colour is not red however when I run the find command below it returns [object]. What am I doing wrong
database: mongoDB
"fruit": {
"color": [
"red"
]
}
Path: server.js
var fruit = fruit.find({
"fruit.color": { $nin: [ red ] },
}).fetch();
If I console log on the server it retuns the following.
console.log(fruit);
{ color: [Object] } } ]
Your find returns an array of objects, that's why you get the [object] result. You have to iterate the result. Like:
var fruits = fruit.find({
"fruit.color": { $nin: [ red ] },
}).fetch();
fruits.forEach(function (afruit) {
console.log(afruit.color);
});