find only matching elements from a JSON array in Ne DB/react native-local-mongo/mongo db - mongodb

i am trying to read only matching keys from a JSON with a nested array.
here is my JSON.
data:[
{
"locale":"en_US",
"pages":[
{
pageName:"testpage1",
"messages":{
"m1":"v1",
"m2":""
}
},
{
pageName:"testpage2",
"messages":{
"m1":"v3",
"m2":"v4"
}
}
]
},
{
"locale":"in_L1",
"pages":[
{
pageName:"testpage1",
"messages":{
"m1":"i1",
"m2":"i2"
}
},
{
pageName:"testpage2",
"messages":{
"m1":"i3",
"m2":"i4"
}
}
]
}
]
I am trying the below query:
db['collec1'].find({locale:"en_US", pages:{$elemMatch:{pageName:"testpage1"},
{locale:1,"pages.pageName":1}}})
also tried,
db['collec1'].find({locale:"en_US", "pages.pageName":"testpage1"},{locale:1,"pages.pageName":1}}})
both are returning, the all the elements in the array as below:
[
{
"locale":"en_US",
pages:{pageName:["testpage1", "testpage2"]}]
}
]
Expected output is:
[
{
"locale":"en_US",
pages:{pageName:["testpage1"]}]
}
]
can someone help me where i am doing it wrong and what needs to be changed?
i am using this library which is a clone of mongodb called Ne DB.

db['collec1'].find({locale:"en_US", pages:{$elemMatch:{pageName:"testpage1"}}).
try with an empty project in the find method {} and then try like
the above example

Related

mongodb query: nested elemMatch

Currently, that's my current document:
{
_id: 'd283015f-91e9-4404-9202-093c28d6a931',
referencedGeneralPractitioner: [
{
resourceType: 'practitioner',
cachedIdentifier: [
{
system: { value: 'urn:oid:1.3.6.1.4.1.19126.3' },
value: { value: '14277399B' }
}
]
}
]
}
Here, there's two nested objects arrays: referencedGeneralPractitioner[{cachedIdentifier[{}]}].
Currently, I'm getting results using this query:
{
"referencedGeneralPractitioner":{
"$elemMatch":{
"cachedIdentifier.value.value":"14277399B",
"cachedIdentifier.system.value":"urn:oid:1.3.6.1.4.1.19126.3"
}
}
}
It's getting my desired document, but I don't quite figure out if above query is which I'm really looking for.
I mean, I'm only applying $elemMatch on referencedGeneralPractitioner field array.
Is it really enought?
Should I add a nested $elemMatch on cachedIdentifier?
Any ideas?
It looks like you need to query it like this:
db.collection.find({
"referencedGeneralPractitioner.cachedIdentifier": {
"$elemMatch": {
"value.value": "14277399B",
"system.value": "urn:oid:1.3.6.1.4.1.19126.3"
}
}
})
playground
This is in case you need to find the full document having $and of both values in same element in any of the elements in the nested array , if you need to extract specific element you will need to $filter
if you need to search also based on element in the 1st array level then you need to modify as follow:
{
"referencedGeneralPractitioner": {
"$elemMatch": {
resourceType: 'practitioner',
"cachedIdentifier": {
"$elemMatch": {
"value.value": 1,
"system.value":2
}
}
}
}
}
This will give you all full documents where at same time there is resouceType:"practitioner" and { value.value:3 and system.value: 2 }
Also is important to stress that this will not gona work correctly!:
{
"referencedGeneralPractitioner":{
"$elemMatch":{
"cachedIdentifier.value.value":"14277399B",
"cachedIdentifier.system.value":"urn:oid:1.3.6.1.4.1.19126.3"
}
}
}
Since it will match false positives based on any single value in the nested elements like:
wrong playground

MongoDB and Flask - Updating objects in a document's array (nested updating)

Assume we have following collection.
{
"Region":"Karnataka",
"ShortCode":"KA",
"SubRegion":[
{
"District":"Banglore",
"Commodity":[
{
"Name":"items",
"isActive":true,
"CommoditySubType":[
{
"Title":"Moistouriser",
"isActive":true,
"hasGrades":true,
"Grade":[
{
"Title":"Premium",
"Rate":"150",
"isActive":true,
"hasRates":true,
"hasSizes":true,
"StartDate":"2021-03-31",
"EndDate":"2021-04-06",
"StartTime":"9:00am",
"EndTime":"6:00pm",
"Sizes":[
{
"Title":"Small",
"isActive":true
}
]
"LastSevenDaysDates":[{
"Date":2021-03-31,
"Price":"150"
}]
}
]
}
]
}
]
},
{
"District":"Coorg",
"Commodity":[]
}
] }
I want to update an object under LastsevndayDates. I tried this.
mongo.db.supplierDailyPrice.update(
{
"Region":region,
"SubRegion.District":district,
"SubRegion.Commodity.Name":commodity,
"SubRegion.Commodity.CommoditySubType.Title":commoditysubtype,
"$and": [
{ "SubRegion.Commodity.CommoditySubType.Grade": { "$exists": True}},
{ "SubRegion.Commodity.CommoditySubType.Grade.Title": "Premium" },
]
},
{
"$set": {
"SubRegion.$[].Commodity.$[].CommoditySubType.$[].Grade.$[].LastSevenDaysDates": Date
}
})
But it's failing with the error pymongo.errors.WriteError: The path 'SubRegion.0.Commodity.0.CommoditySubType.1.Grade' must exist in the document in order to apply array updates.
You can use arrayFilters to solve your problem
db.supplierDailyPrice.update({
"Region":region
},
{
$set:{
"Subregion.$[sub].Commodity.$[com].CommoditySubType.$[Cst].Grade.$[grd]. LastSevenDaysDates.$[sev].date": Date
}
},
{
array_filter : [
{"sub.district": district},
{"com.name": commodity},
{"Cst.title": commoditysubtype},
{"grd.title": "premium"},
{"sev.price":"150"},
]
})
Not tested the code but something like this will solve your problem. For more reference you can check out the links below:
Update deeply nested array in mongodb
update deeply nested array mongodb
Pymongo error for ArrayFilters to update multiple subdocuments
Ujjwal's answer is on the right track. I fixed a few typos.
More information here about $[] usage.
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/
https://developer.mongodb.com/how-to/update-array-elements-document-mql-positional-operators/
db.supplierDailyPrice.update_one({
"Region": region
},
{
$set:{
"SubRegion.$[sub].Commodity.$[com].CommoditySubType.$[cst].Grade.$[grd].LastSevenDaysDates.$[sev].Date": "2021-04-03"
}
},
{
"array_filters" : [
{"sub.District": district},
{"com.Name": commodity},
{"cst.Title": commoditysubtype},
{"grd.Title": grade},
{"sev.Price":"150"},
]
},
{
upsert=true
}
)

Update specific element in nested array

I have the following structure
{
"_id":"5b609d1a5b4e2c03e512992b",
"files_missing":5,
"files_rejected":0,
"userId":"5afcbbcf26d784ca35fac580",
"files":[
{
"status":"sent",
"_id":"5b609d1a5b4e2c03e5129930",
"fileId":"5afcbad526d784ca35fac576",
"urls" [
{
"_id":"5b60e10114bce7084cebc1da",
"file":"/data/5b609d195b4e2c03e512992a.pdf",
"status":"sent"
},{
"_id":"5b60e1ea14bce7084cebc1dd",
"file":"/data/5b60e1ea14bce7084cebc1dd.pdf",
"status":"sent"
}
]
}
],
"contactId":"5b609d195b4e2c03e512992a",
"created_at":"2018-07-31T17:32:10.251Z",
"updated_at":"2018-07-31T17:32:10.251Z",
}
And I want to update the status inside in one of the elements of urls
I tried:
db.collection.update({contactId:"5b609d195b4e2c03e512992a",
'files.urls._id': "5b60e1ea14bce7084cebc1dd"},{$set:
{'files.urls.$.status': 'rejected'}})
MongoDB version: 3.2.17

Retrieve only matched sub document from MongoLab/MongoDB through http/REST

Is it possible to retrieve only sub document from an object array in MongoDB collection which matches specified query Using REST HTTP interface.
There are many already answer for similar questions, but those are for using MongoDB driver, not REST/HTTP
Any possibility ?
Sample data
[
{
"name":"Paul",
"addresses":[
{
"addressline1":"Street no1",
"city":"Delhi"
},
{
"addressline1":"Street no4",
"city":"Chennai"
}
]
},
{
"name":"Rose",
"addresses":[
{
"addressline1":"Street no5",
"city":"Delhi"
},
{
"addressline1":"Street no7",
"city":"Chennai"
}
]
}
]
From above data I only need to get single address, which 'name' matching 'Paul' and 'city' matching 'Delhi' as below
{
"addressline1":"Street no1",
"city":"Delhi"
}
I have below query to search within sub document. But it returns all elements in sub document array which contains this sub document query.
https://api.mongolab.com/api/1/databases/[mydb]/collections/[mycollection?
apiKey=[myAPIKey]
&q={"name":"Paul","addresses.city":{"$regex":"^Delhi$","$options":"i"}}
&f={"addresses":1}
But above query returns
{
"addresses":[
{
"addressline1":"Street no1",
"city":"Delhi"
},
{
"addressline1":"Street no4",
"city":"Chennai"
}
]
}
Try this:
https://...&f={"addresses.$":1}
Note that I used the $ projection operator in the query above.

How to create a criteria in Grails with a conjunction(and) of two disjunctions(or) using MongoDB?

I'm trying to get all the activities from a user or its teams also filtered by some types if some properties are set.
This is what I have right now:
Activity.withCriteria{
and{
or {
eq 'user',myUser
"in" 'team',userTeams
}
and{
if (showA || showB || showC){
or{
if (showA){
"in" "a", myAList
}
if (showB){
"in" "b", myBList
}
if (showC){
"in" "c",myCList
}
}
}
}
}
order "date","desc"
maxResults maxElements
}
Executing that, what I get it's the OR of user and team block and the showA, showB, showC block instead of the AND of those two blocks.
I'm using grails 2.2.1 (also using MongoDB GORM 1.2.0 without Hibernate)
EDIT:
I have been able to see the query that's sent to MongoDB and it's not doing the first part of the criteria.
This is the query that's being passed to MongoDB:
query: { query: { $or: [ { a: { $in: [ "5191e2c7c6c36183687df8b6", "5191e2c7c6c36183687df8b7", "5191e2c7c6c36183687df8b8" ] } }, { b: { $in: [ "5191e2c7c6c36183687df8b9", "5191e2c7c6c36183687df8ba", "5191e2c7c6c36183687df8bb" ] } }, { c: { $in: [ "5191e2c7c6c36183687df8b5" ] } } ] }, orderby: { date: -1 } } ntoreturn: 10 ntoskip: 0
EDIT: I have just seen that a JIRA has already been raised and it seems that's a MongoDB plugin problem...
http://jira.grails.org/browse/GPMONGODB-296
You can think in your criteria in a SQL perspective.
and ((user = 'myUserValue'
or team in (...))
and(a in (...)
or b in (...)
or c in (...)))
So your or is applied to user and team, but I think you want something like:
or {
and {
eq 'user',myUser
"in" 'team',userTeams
}
and{
if (showA || showB || showC){
or{
if (showA){
"in" "a", myAList
}
if (showB){
"in" "b", myBList
}
if (showC){
"in" "c",myCList
}
}
}
}
}
So the key here is that the block you declare is applied to what you have inside.
EDIT:
A good tip to inspect a criteria is to enable the output of sql's generated by Hibernate. This can be done in DataSource.groovy
dataSource {
logSql = true
}
hibernate {
format_sql = true
}
With the new version of Mongo for Grails this has been fixed, so now it's working with version 1.3.0.
http://grails.org/plugin/mongodb