Mongodb Search nested array elements - mongodb

I have a below data. Would like to search aclpermissions where any of the elements (CRT, READ, DLT, UPD) will match to an array of inputs.
Below query
db.AMSAppACL.find({"aclpermissions.READ" : {'$in': ['58dc0bea0cd182789fc62fab']}}).pretty();
only searches READ element. Is there any way to search all the elements instead of using or queries and aggregate
{
"_id" : ObjectId("5900d6abb9eb284a78f5a350"),
"_class" : "com.debopam.amsapp.model.AMSAppACL",
"attrUniqueCode" : "USER",
"attributeVersion" : 1,
"aclpermissions" : {
"CRT" : [
"58dc0bd70cd182789fc62faa"
],
"READ" : [
"58dc0bd70cd182789fc62faa",
"58dc0bea0cd182789fc62fab"
],
"UPD" : [
"58dc0bd70cd182789fc62faa"
],
"DLT" : [
"58dc0bd70cd182789fc62faa"
]
},
"orgHierachyIdentifier" : "14",
"orgid" : 14,
"createDate" : ISODate("2017-04-26T17:19:39.026Z"),
"lastModifiedDate" : ISODate("2017-04-26T17:19:39.026Z"),
"createdBy" : "appadmin",
"lastModifiedBy" : "appadmin"
}

You should try updating aclpermissions part of schema from dynamic keys to labeled keys.
"aclpermissions":
[
{k:"CRT", v: ["58dc0bd70cd182789fc62faa"]},
{k:"READ", v: [ "58dc0bd70cd182789fc62faa", "58dc0bea0cd182789fc62fab"]}....
]
Now you can update the query from post to something like
db.AMSAppACL.find({"aclpermissions.v" : {'$in': ['58dc0bea0cd182789fc62fab']}}).pretty();

Related

MongoDB delete specific nested element in object array

I want to remove this
"lightControl" : 75
from this
{
"_id" : "dfdfwef-fdfd-fd94284o-aafg",
"name" : "Testing",
"serialNumber" : "fhidfhd8ghfd",
"description" : "",
"point" : {
"type" : "Point",
"coordinates" : [
10.875447277532754,
20.940549069378634
]
},
"ancestors" : [ ],
"metadata" : {
"measurement" : {
"high" : "40000.0",
"medium" : "25000.0"
},
"digitalTwin" : {
},
"emails" : [
""
],
"lastMeasurementDate" : "2010-03-04T11:32:06.691Z",
"lightControl" : 75
},
"tags" : [ ],
"createdAt" : ISODate("2019-12-07T15:22:10.988Z"),
"updatedAt" : ISODate("2020-03-08T15:38:21.736Z"),
"_class" : "com.test.demo.api.model.Device"
}
All I want is for this specific id, to completely delete the lightControl element from metadata. I have tried $pull, but I am probably missing something. Any ideas? Thank you in advance!
Your lightControl is not in array, for nested property, use the dot wrapped in doublequotes:
MongoDB shell:
db.getCollection('yourCollectionName').update({},{$unset:{
"metadata.lightControl":""
}})
In case you have a list of objects with _id(s) instead of updating directly, assume Node.js client for MongoDB is used:
// import mongodb from "mongodb"; // ES6
const mongodb = require("mongodb");
var client = MongoClient(...);
var coll = client["yourDbName"]["yourCollectionName"];
var objs = []; // <-- The array with _id(s)
for (let i=0; i<objs.length; i++){
let id = mongodb.ObjectID(objs[i]["_id"]);
coll.update({ _id:id },{$unset:{ "metadata.lightControl":"" }});
}

How to iterate a mongo db document and update a nested array

I need to remove entries inside a 2d array of documents structure in mongodb.
Sample is as below
{
"_id" : ObjectId("5ffef283f1f06ff8524aa2c2"),
"applicationName" : "TestApp",
"pName" : "",
"environments" : [],
"stages" : [],
"createdAt" : ISODate("2021-01-15T09:51:35.546Z"),
"workflows" : [
[
{
"pName" : "Test1",
"wName" : "TestApp_Test1",
"agent" : ""
},
{
"pName" : "Test2",
"wName" : "TestApp_Test2",
"agent" : ""
}
],
[
{
"pName" : "Test1",
"wName" : "TestApp_Test1",
"agent" : ""
}
]
],
"updatedAt" : Date(-62135596800000)
}
So, I want to remove all document occurences of
{
"pName" : "Test1",
"wName" : "TestApp_Test1",
"agent" : ""
}
from both the arrays.
pName:Test1 can be used to filter it out.
What's the query which can be used to find this and delete it ?
I am ok to do a find and then iterate over the collection , find the matching entry and then update the document. I have to do this using Go mongodb driver
Since this is kind of complex for me as I am new to both golang and mongo db, I am stuck.
Update:
1.Tried {$pull: {workflows: {pName:"Test1"}}}, {multi: true} in the update() call as suggested but didn't work.
2.Tried something like this
db.getCollection('workflows').update({_id:ObjectId('5ffef283f1f06ff8524aa2c2')}, {$pull:{workflows: { $elemMatch: {pName:'Test2'}}}} )
This is removing the entire array as shown below because Test2 is present in that. I need to remove only the Test2 document
[
{
"pName" : "Test1",
"wName" : "TestApp_Test1",
"agent" : ""
},
{
"pName" : "Test2",
"wName" : "TestApp_Test2",
"agent" : ""
}
]
I'll give you a hint as you are new and you haven't posted the tried things.
You could use $pull to remove documents matching the conditions.
similar example
And you could use official mongodb driver for go or most used gopkg
An example SO post

How to search nearest place in array object in mongodb

the mongodb document 'contents' is
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"name" : "4Fingers",
"locations" : [
{
"id" : "locations1",
"address" : "68 Orchard Rd, #B1-07 Plaza Singapura, Plaza Singapura, Singapura 238839",
"phone" : "+65 6338 0631",
"openhours" : "Sunday-Thursday: 11am - 10pm \nFriday/Saturday/Eve of PH*: 11am - 11pm",
"loc" : [
"1.300626",
"103.845061"
]
}
],
"comments" : [ ],
"modified" : 1472271793525,
"created" : 1472012276724,
"createdby" : "Admin",
"modifiedby" : "Admin",
"createdipaddress" : "localhost",
"modifiedipaddress" : null,
"types" : "Restaurant",
"category" : "FoodAndBeverages",
"logo" : "logo4Fingers.png",
"tags" : "western, chicken, restaurant, food, beverages"
}
I want to find the nearest place to my location that i get from HTML5 navigation. How do i query it? Data should be sorted in near to far order.
Thank you.
To query mongodb geospatial data first you need a geo spatial index on your location field.
Your location field is a string, it needs to be a numeric type, you need to update your data accordingly.
Create your index on numerical location data:
db.collection.createIndex( { "locations.loc" : "2d" });
Query:
var projection = {"locations.loc":1};
var query = {"locations.loc": {"$near":[1.300626, 103.845061], "$maxDistance": 0.5}};
db.collection.find(query, projection).pretty();
//result:
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"locations" : [
{
"loc" : [
1.300626,
103.845061
]
}
]
}
var query2 = {"locations.loc": {"$near":[2.300626, 103.845061], "$maxDistance": 0.5}};
db.collection.find(query2, projection).pretty();
//result:
{}
The query result will be sorted always, with nearest as first document.
Thanks Sergiu Zaharie.
It's working.
Then how can i returned all the field instead of returning this field only.
{
"_id" : ObjectId("57bd1ff410ea3c38386b9194"),
"locations" : [
{
"loc" : [
103.845061,
1.300626
]
}
]
}
//edit
Solved.
i just clear the projection then it work like charm.
Thank you.

Druid aggregate functions

I am using druid to create a UI for generating reports. For the scripting, I am using the following codes:
{
"type" : "doubleSum",
"name" : "impressions",
"fieldName" : "impressions"
},
{
"type" : "doubleSum",
"name" : "clicks",
"fieldName" : "clicks"
},
{
"type" : "doubleSum",
"name" : "pvconversions",
"fieldName" : "pvconversions"
},
{
"type" : "doubleSum",
"name" : "pcconversions",
"fieldName" : "pcconversions"
}
I need two more fields:
Total Conversions = pvconversions+pcconversions
CTR = Clicks / Impressions
I havent been able to find anything regarding this matter about how to write them.
Can anyone help.
Thanks
Your issue can be resolve using aggregations and postAggregations like this snippets below:
{
"queryType":"timeseries",
"dataSource":"data",
"granularity":"hour",
"descending":"false",
"aggregations":[
{"type":"doubleSum", "name":"sum-pvconversions", "fieldName":"pvconversions"},
{"type":"doubleSum", "name":"sum-pcconversions", "fieldName":"pcconversions"},
{"type":"doubleSum", "name":"sum-clicks", "fieldName":"clicks"},
{"type":"doubleSum", "name":"sum-impressions", "fieldName":"impressions"}
],
"postAggregations":[
{
"type":"arithmetic",
"name":"Conversions",
"fn":"+",
"fields":[
{"type":"fieldAccess", "name":"postAgg-proceed", "fieldName":"sum-pvconversions"},
{"type":"fieldAccess", "name":"postAgg-numbers", "fieldName":"sum-pcconversions"}
]
},
{
"type":"arithmetic",
"name":"CTR",
"fn":"/",
"fields":[
{"type":"fieldAccess", "name":"postAgg-click", "fieldName":"sum-clicks"},
{"type":"fieldAccess", "name":"postAgg-impression", "fieldName":"sum-impressions"}
]
}
],
"intervals":["2016-08-22T01/2016-08-29T03"],
"context":{
"skipEmptyBuckets":"true"
}
}
You can do it by using aggregate in timeseries query. Is that not what you are looking for?
Aggregations in Druid can only be used with aggregation queries like timeseries, topN and groupBy.
If you're just aggregating values in a column against time, the simplest way to do it would be to write a timeseries query.
For example,
{
"queryType": "timeseries",
"dataSource": "<datasource name>",
"granularity": "day",
"aggregations": [
<Your aggregations here>
],
"intervals": [ <Time interval (from/to)> ]
}
You have to use post aggregates in the query.
From the documentation of Druid
Post-aggregations are specifications of processing that should happen on aggregated values as they come out of Druid. If you include a post aggregation as part of a query, make sure to include all aggregators the post-aggregator requires
For example to calculate CTR, here is the post aggregate:
"postAggregations" : [{
"type" : "arithmetic",
"name" : "average",
"fn" : "*",
"fields" : [
{ "type" : "arithmetic",
"name" : "CTR",
"fn" : "/",
"fields" : [
{ "type" : "fieldAccess", "name" : "clicks", "fieldName" : "clicks" },
{ "type" : "fieldAccess", "name" : "impressions", "fieldName" : "impressions" }
]
}

Mongodb + Mongoose: trying to add a sub-sub-item

Does this makes any sense when trying to add a sub-sub-item? (I'm new to mongo - be merciful :-))
question = db.questions.findOne({_id: ObjectId("529c5d44211c9a8c11000006")})
question.answers[0].votes.insert(...)
When I run this from the mongo console the result is an error saying [object object] does not have the method insert.
I have the following mongoDB Question Schema.
{
"__v" : 2,
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d44211c9a8c11000006"),
"answers" : [
{
"postDate" : ISODate("2013-12-02T10:14:19.060Z"),
"postDateText" : "15min ago",
"authorEmail" : "guys#pix.com",
"authorName" : "guys#pix.com",
"body" : "You need magic powder",
"isWinner" : false,
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d7b211c9a8c11000008"),
"votes" : [
{
"voteType" : "up",
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d5b211c9a8c11000007")
}
]
}
],
"authorEmail" : "guys#wix.com",
"authorName" : "guys#wix.com",
"body" : "I'm trying to fly...\n\n<pre class=\"brush: js;\">\nfunction logName(name) {\n console.log(name);\n}\n</pre>",
"isResolved" : false,
"postDate" : ISODate("2013-12-02T10:13:24.235Z"),
"tags" : [
"fly"
],
"title" : "How do I fly?",
"views" : [],
"votes" : [
{
"voteType" : "up",
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d5b211c9a8c11000007")
}
]
}
I'm trying, given a questionId and an answerId to add a vote to the votes array (which is inside the answer). I can't seem to do it. Help?
insert is for adding whole new documents; when you just want to add a new element to an array field of an existing document, you can use update along with an operator like $push.
So, in the shell you would use something like this:
db.questions.update(
{_id: ObjectId("529c5d44211c9a8c11000006")},
{'answers.0.votes': {$push: voteToPush}})