I have this code in Swift 4 and Alamofire:
Alamofire.request("http://xxxx.pl/id=1", method: .get, parameters: nil)
.responseJSON { response in
let jsonResponse = JSON(response.result.value!)
let resData = jsonResponse["ranking"].array
print("XXXX: \(jsonResponse)")
}
.responseString { response in
if let error = response.result.error {
print(error)
}
if let value = response.result.value {
print(value)
}
}
After running this code, I get a json with the following parameters:
XXXX: {
"ranking" : {
"dataWidoczneOd" : {
"second" : 0,
"year" : 2018,
"month" : 2,
"hourOfDay" : 0,
"dayOfMonth" : 1,
"minute" : 0
}
"opis" : "cx",
"id" : 50971,
"dataWidoczneDo" : {
"second" : 0,
"year" : 2018,
"month" : 2,
"hourOfDay" : 0,
"dayOfMonth" : 31,
"minute" : 0
},
"grupy" : [
{
"nazwa" : "yyy",
"kod" : "yyy",
"id" : 51032,
"idkiPlikowGrafiki" : [
"51034"
],
"gracze" : [
{
"zakonczonaGra" : false,
"imieINazwisko" : "zzzz yyyy",
"email" : "tertretera#cccc.com",
"liczbaZdobytychPunktow" : "0.0",
"czasGry" : "0 min"
}
]
},
{
"nazwa" : "ttt",
"kod" : "ttt",
"id" : 50981,
"idkiPlikowGrafiki" : [
"50983",
"50986"
],
"gracze" : [
]
}
],
"nazwa" : "grupowy",
"idkiPlikowGrafiki" : [
"50976"
],
"typ" : "GRUPA",
"dataOd" : {
"second" : 0,
"year" : 2018,
"month" : 2,
"hourOfDay" : 0,
"dayOfMonth" : 1,
"minute" : 0
}
}
}
How can I get the values from this json array and save in variables:
- gracze (all values)
- idkiPlikowGrafiki (all values)
- typ (all values)
- kod (all values)
- dataWidoczneOd (all values)
?
Please help :)
You should create a model class for this response and parse it with, for example, Codable. Here is a good example.
Related
My database has 3 Collections :
Tour, 2) turism_ind, 3) customer
> db.tour.find({}).pretty()
{
"_id" : ObjectId("622385ab1b68d9136e48ba51"),
"source" : "Pune",
"destination" : "Kashmir"
}
{
"_id" : ObjectId("622385ba1b68d9136e48ba52"),
"source" : "Mumbai",
"destination" : "Shilong"
}
{
"_id" : ObjectId("622385ce1b68d9136e48ba53"),
"source" : "Nashik",
"destination" : "Goa"
}
> db.turism_ind.find({}).pretty()
{
"_id" : ObjectId("6223885d1b68d9136e48ba57"),
"ind_name" : "Veena World",
"package" : [
{
"pkg_id" : 111,
"tour_id" : ObjectId("622385ba1b68d9136e48ba52"),
"cost" : 85000
}
],
"cust_review" : [
{
"cust_id" : ObjectId("622387fa1b68d9136e48ba56"),
"rating" : 4
}
]
}
{
"_id" : ObjectId("622389191b68d9136e48ba58"),
"ind_name" : "GK Travels",
"package" : [
{
"pkg_id" : 222,
"tour_id" : ObjectId("622385ba1b68d9136e48ba52"),
"cost" : 82000
},
{
"pkg_id" : 223,
"tour_id" : ObjectId("622385ab1b68d9136e48ba51"),
"cost" : 78000
}
],
"cust_review" : [
{
"cust_id" : ObjectId("622387f51b68d9136e48ba55"),
"rating" : 5
}
]
}
{
"_id" : ObjectId("622389ae1b68d9136e48ba59"),
"ind_name" : "KK Tours",
"package" : [
{
"pkg_id" : 333,
"tour_id" : ObjectId("622385ce1b68d9136e48ba53"),
"cost" : 57000
},
{
"pkg_id" : 334,
"tour_id" : ObjectId("622385ab1b68d9136e48ba51"),
"cost" : 79000
}
],
"cust_review" : [
{
"cust_id" : ObjectId("622387f51b68d9136e48ba55"),
"rating" : 5
},
{
"cust_id" : ObjectId("622387ef1b68d9136e48ba54"),
"rating" : 4
}
]
}
> db.customer.find({}).pretty()
{
"_id" : ObjectId("622387ef1b68d9136e48ba54"),
"cust_name" : "Aniket",
"selected_pkg" : [
111
]
}
{
"_id" : ObjectId("622387f51b68d9136e48ba55"),
"cust_name" : "Nik",
"selected_pkg" : [
222,
333,
334
]
}
{
"_id" : ObjectId("622387fa1b68d9136e48ba56"),
"cust_name" : "Sham",
"selected_pkg" : [
111,
222
]
}
{
"_id" : ObjectId("62238c671b68d9136e48ba5a"),
"cust_name" : "John",
"selected_pkg" : [
111,
222,
223,
333,
334
]
}
I want to perform the following queries :
1] List all the details of expenses made by John on his first 3 trips.
Also display the total expenses
2] List the names of the customers who went on a tour to Shillong. [5]
It is possible to perform those queries on the given document or document structure is wrong?
I try this for 1st query
db.turism_ind.aggregate(
{$unwind : "$package"},
{$match : { "package.pkg_id" : {$in : [111,222,333] } } },
{$project :{ _id : 0 , package : 1, total_cost : {$sum : "$package.cost"} }}
)
Output (Not Correct)
{ "package" : { "pkg_id" : 111, "tour_id" : ObjectId("622385ba1b68d9136e48ba52"), "cost" : 85000 }, "total_cost" : 85000 }
{ "package" : { "pkg_id" : 222, "tour_id" : ObjectId("622385ba1b68d9136e48ba52"), "cost" : 82000 }, "total_cost" : 82000 }
{ "package" : { "pkg_id" : 333, "tour_id" : ObjectId("622385ce1b68d9136e48ba53"), "cost" : 57000 }, "total_cost" : 57000 }
Here is the aggregation for your first part. There might be some bug depending on your other documents inside your collections.
Here's a quick breakdown of your question.
List all the details of expenses made by John
Utilize $match to get john document
on his first 3 trips.
Utilize $project to slice the first 3 elements out and the do a $lookup on the turism_ind to grab the necessary documents
Also display the total expenses
Had to utilize the $reduce in a projection to flatten 2D array into 1D, and follow by another project to $sum all the cost together as total.
MongoDB Playground
db.customer.aggregate([
{
"$match": {
"cust_name": "John"
}
},
{
"$project": {
"firstThree": {
"$slice": [
"$selected_pkg",
0,
3
]
}
}
},
{
"$lookup": {
"from": "turism_ind",
"localField": "firstThree",
"foreignField": "package.pkg_id",
"as": "tour"
}
},
{
"$project": {
"_id": 0,
"packages": {
$reduce: {
input: "$tour.package",
initialValue: [],
in: {
$concatArrays: [
"$$value",
"$$this"
]
}
}
}
}
},
{
"$project": {
"packages": 1,
"total": {
"$sum": "$packages.cost"
}
}
}
])
Result
[
{
"packages": [
{
"cost": 85000,
"pkg_id": 111,
"tour_id": ObjectId("622385ba1b68d9136e48ba52")
},
{
"cost": 82000,
"pkg_id": 222,
"tour_id": ObjectId("622385ba1b68d9136e48ba52")
},
{
"cost": 78000,
"pkg_id": 223,
"tour_id": ObjectId("622385ab1b68d9136e48ba51")
}
],
"total": 245000
}
]
Hey guys I'm trying to update a value that is in an array in MongoDB, am trying to use the mongo queries but is not working, am following the next documentation from Mongo doc
this one is the array:
{
"_id" : "605e3d9b9ef219de662113d0",
"distribution" : [
{
"floor" : 1,
"rooms" : [
{
"number" : 301,
"beds" : [
{
"number" : 818,
"status" : "Vacante Sucia"
},
{
"number" : 819,
"status" : "Vacante Sucia"
}
],
"gender" : "M"
},
{
"number" : 302,
"beds" : [
{
"number" : 820,
"status" : "Vacante Sucia"
},
{
"number" : 821,
"status" : "Vacante Sucia"
}
],
"gender" : "M"
},
{
"number" : 303,
"beds" : [
{
"number" : 822,
"status" : "Vacante Sucia"
},
{
"number" : 823,
"status" : "Vacante Sucia"
}
],
"gender" : "M"
}
]
}
],
"name" : "Meteorologia",
"code" : "METEO"
}
this one is the query that is using in mongoDB to update the status from the bed 801, room 301, floor 1:
in the arrayFilters i specified the index 0 to get the first element of the arrays
db.getCollection('establishments_copy').findAndModify({query: { code: "METEO"}, update: { $set: { "distribution.$[i].rooms.$[i].beds.$[i].status": "TEST"}}, arrayFilters: [{"i.rooms": 0, "i.beds": 0, "i.status": 0}]})
they are returning me the collection but without changes, is possible to navigate validating not for the index just with the values.
for example using the next query:
db.getCollection('establishments_copy').findAndModify({query: { code: 'METEO', distribution: { $elemMatch: { floor: 1, 'rooms.number': 301, 'rooms.beds.number': 818}}}, update: { $set: { '...': 'CHANGED'}}})
thanks!
You just need to create separate condition as per sub document's field name,
f for floor field in distribution array
r for number field in rooms array
b for number field in beds array
db.getCollection('establishments_copy').findAndModify({
query: { code: "METEO"},
update: {
$set: {
"distribution.$[f].rooms.$[r].beds.$[b].status": "TEST"
}
},
arrayFilters: [
{ "f.floor": 1 },
{ "r.number": 301 },
{ "b.number": 818 }
]
})
Playground
I have a a few documents that have the following structure. See attached image.
document structure
Each document includes an array of 'FileMeta' objects and each FileMeta object includes an array of 'StatusHistory' objects. I'm trying to get only the FileMetas that contain StatusCode equal to 4 and that the TimeStamp is greater than a certain datetime.
Tried the following query but it only returns the first FileMeta element of each document.
db.getCollection('Collection').find({'ExternalParams.RequestingApplication':'aaa.bbb'},
{ "FileMeta": { $elemMatch: { "StatusHistory":{ $elemMatch:{ "StatusCode": 4, "TimeStamp": { $gt: ISODate("2020-06-28T11:02:26.542Z")} } } } }} )
What am I doing wrong?
here is the document structure:
{
"_id" : ObjectId("5ef84e2ec08abf38b0043ab4"),
"FileMeta" : [
{
"StatusHistory" : [
{
"StatusCode" : 0,
"StatusDesc" : "New File",
"TimeStamp" : ISODate("2020-06-28T11:00:46.286Z")
},
{
"StatusCode" : 2,
"StatusDesc" : "stby",
"TimeStamp" : ISODate("2020-06-28T11:02:20.400Z")
},
{
"StatusCode" : 4,
"StatusDesc" : "success",
"TimeStamp" : ISODate("2020-06-28T11:02:26.937Z")
}
]
},
{
"StatusHistory" : [
{
"StatusCode" : 0,
"StatusDesc" : "New File",
"TimeStamp" : ISODate("2020-06-28T11:00:46.286Z")
},
{
"StatusCode" : 2,
"StatusDesc" : "stby",
"TimeStamp" : ISODate("2020-06-28T11:02:20.617Z")
},
{
"StatusCode" : 4,
"StatusDesc" : "success",
"TimeStamp" : ISODate("2020-06-28T11:02:26.542Z")
}
]
}
],
}
I want to return only the FileMeta objects that include a StatusHistory that match the following conditions: StatusCode = 4 and TimeStamp > SomeDateTime
Sorry for the delay, mate, I've been quite busy lately. Hope you already solved your problem. Anyway, I think that I found the solution.
As you can see on this link, the example shows that by default the $elemMatch operator returns the whole array in case of match on any element.
For instance, consider the following collection:
{ _id: 1, results: [ { product: "abc", score: 10 }, { product: "xyz", score: 5 } ] }
{ _id: 2, results: [ { product: "abc", score: 8 }, { product: "xyz", score: 7 } ] }
{ _id: 3, results: [ { product: "abc", score: 7 }, { product: "xyz", score: 8 } ] }
If you do the following query, for example:
db.survey.find(
{ results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } }
)
The output will be:
{ "_id" : 3, "results" : [ { "product" : "abc", "score" : 7 }, { "product" : "xyz", "score" : 8 } ] }
Not:
{ "_id" : 3, "results" : [{ "product" : "xyz", "score" : 8 }]}
That said, if you want to return only the document in the array that matches the specified query, you must use the db.collection.aggregate() function with the $unwind and $match operator.
The query below shall give you what you want.
Query:
db.collection.aggregate([
{"$unwind" : "$FileMeta"},
{"$unwind" : "$FileMeta.StatusHistory"},
{
"$match" : {
"FileMeta.StatusHistory.StatusCode" : 4,
"FileMeta.StatusHistory.TimeStamp" : {"$gte" : ISODate("2020-06-28T11:02:26.937Z")}
}
}
]).pretty()
Result:
{
"_id" : ObjectId("5ef84e2ec08abf38b0043ab4"),
"FileMeta" : {
"StatusHistory" : {
"StatusCode" : 4,
"StatusDesc" : "success",
"TimeStamp" : ISODate("2020-06-28T11:02:26.937Z")
}
}
}
One last tip. Consider changing your modeling to something that looks like the unwinded document, and remember that one document should be equivalent to one row in a normal relational database. So avoid storing information that should be on "several rows" on a single document.
Useful links:
The $elemMatch operator.
The $unwind operator.
I am trying to remove duplicates from MongoDB but all solutions find fail.
My JSON structure:
{
"_id" : ObjectId("5d94ad15667591cf569e6aa4"),
"a" : "aaa",
"b" : "bbb",
"c" : "ccc",
"d" : "ddd",
"key" : "057cea2fc37aabd4a59462d3fd28c93b"
}
Key value is md5(a+b+c+d).
I already have a database with over 1 billion records and I want to remove all the duplicates according to key and after use unique index so if the key is already in data base the record wont insert again.
I already tried
db.data.ensureIndex( { key:1 }, { unique:true, dropDups:true } )
But for what I understand dropDups were removed in MongoDB > 3.0.
I tried also several of java script codes like:
var duplicates = [];
db.data.aggregate([
{ $match: {
key: { "$ne": '' } // discard selection criteria
}},
{ $group: {
_id: { key: "$key"}, // can be grouped on multiple properties
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}}
],
{allowDiskUse: true} // For faster processing if set is larger
).forEach(function(doc) {
doc.dups.shift(); // First element skipped for deleting
doc.dups.forEach( function(dupId){
duplicates.push(dupId); // Getting all duplicate ids
}
)
})
and it fails with:
QUERY [Js] uncaught exception: Error: command failed: {
“ok“: 0,
“errmsg“ : “assertion src/mongo/db/pipeline/value.cpp:1365“.
“code“ : 8,
“codeName" : “UnknownError“
} : aggregate failed
I haven't change MongoDB settings, working with the default settings.
This is my input collection dups, with some duplicate data (k with values 11 and 22):
{ "_id" : 1, "k" : 11 }
{ "_id" : 2, "k" : 22 }
{ "_id" : 3, "k" : 11 }
{ "_id" : 4, "k" : 44 }
{ "_id" : 5, "k" : 55 }
{ "_id" : 6, "k" : 66 }
{ "_id" : 7, "k" : 22 }
{ "_id" : 8, "k" : 88 }
{ "_id" : 9, "k" : 11 }
The query removes the duplicates:
db.dups.aggregate([
{ $group: {
_id: "$k",
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $project: { k: "$_id", _id: { $arrayElemAt: [ "$dups", 0 ] } } }
] )
=>
{ "k" : 88, "_id" : 8 }
{ "k" : 22, "_id" : 7 }
{ "k" : 44, "_id" : 4 }
{ "k" : 55, "_id" : 5 }
{ "k" : 66, "_id" : 6 }
{ "k" : 11, "_id" : 9 }
As you see the following duplicate data is removed:
{ "_id" : 1, "k" : 11 }
{ "_id" : 2, "k" : 22 }
{ "_id" : 3, "k" : 11 }
Get the results in an array:
var arr = db.dups.aggregate([ ...] ).toArray()
The arr has the array of the documents:
[
{
"k" : 88,
"_id" : 8
},
{
"k" : 22,
"_id" : 7
},
{
"k" : 44,
"_id" : 4
},
{
"k" : 55,
"_id" : 5
},
{
"k" : 66,
"_id" : 6
},
{
"k" : 11,
"_id" : 9
}
]
Hi I'm trying to reach embedded document inside this array:
"_id" : 0,
"name" : "Sykes",
"orders" : [
{
"invoiceNumber" : 788,
"cart" : [
{
"item" : 0,
"pkgId" : 3,
"qty" : 10
}
]
},
{
"invoiceNumber" : 801,
"cart" : [
{
"item" : 1,
"pkgId" : 1,
"qty" : 8
}
]
}
I've tried this:
db.customer.find({_id:1},{'orders.invoiceNumber':1,_id:0}).pretty()
I need to convert this command to PHP. Any help please?