AFNetworking valueForKeyPath Wildcard - iphone

Im trying to get the tvrage_name from the following JSON file.
{
data: {
Band of Brothers: {
air_by_date: 0,
cache: {
banner: 1,
poster: 1
},
language: "en",
network: "HBO",
next_ep_airdate: "",
paused: 0,
quality: "Any",
status: "Ended",
tvdbid: 74205,
tvrage_id: 2708,
tvrage_name: "Band of Brothers"
},
Breaking Bad: {
air_by_date: 0,
cache: {
banner: 1,
poster: 1
},
language: "en",
network: "AMC",
next_ep_airdate: "2013-07-14",
paused: 0,
quality: "HD",
status: "Continuing",
tvdbid: 81189,
tvrage_id: 18164,
tvrage_name: "Breaking Bad"
},
},
message: "",
result: "success"
}
Is there any way to have a wildcard in the valueForKeyPath?
So the valueForKeyPath would be: data.*.tvrage_name (the * would be the wildcard)

No. You will have to loop over the key/values like this*:
...
NSDictionary *data = [JSON valueForKey:#"data"];
for (NSString *movie in data) {
NSLog(#"tvrage_name: %#", [[data valueForKey:movie] valueForKey:#"tvrage_name"]);
}
...
*I like to be on the safe side so I always have extra checks. e.g. [JSON isKindOfClass:[NSDictionary class]], etc.
Hope it helps.

If you get a copy of the dictionary with just the tv show entries (not 'message' and 'result'), then you can do [[shows allValues] valueForKeyPath:#"tvrage_name"]
This should work since allValues gives you an array of dictionaries and so valueForKeyPath will in turn give you an array of values under the given key.
(However it's probably a bad idea to do this without additional checks or hardening when getting JSON over a network, in case the JSON is not structured as you expected)

Related

mongodb need to populate a new field with an old fields value, without destroying other data

I have a situation where a model changed at some point in time and I am faced with (for argument sake) half my data liks like this
{
_id: OID,
things: [{
_id:OID,
arm: string,
body: string
}],
other: string
}
and the other half of my data look like this
{
_id: OID,
things: [{
_id:OID,
upper_appendage: string,
body: string
}],
other: string
}
I would like to 'correct' half of the data - so that I DON'T have to accommodate both names for 'arm' in my application code.
I have tried a couple different things:
The first errors
db.getCollection('x')
.find({things:{$exists:true}})
.forEach(function (record) {
record.things.arm = record.things.upper_appendage;
db.users.save(record);
});
and this - which destroys all the other data in
db.getCollection('x')
.find({things:{$exists:true}})
.forEach(function (record) {
record.things = {
upper_appendage.arm = record.things.upper_appendage
};
db.users.save(record);
});
Keeping in mind that there is other data I want to maintain...
How can I do this???
the $rename operator should have worked for this job but unfortunately it doesn't seem to support nested array fields (as of mongodb server 4.2). instead you'd need a forEach like the following:
db.items.find({
things: {
$elemMatch: {
arm: {
$exists: true
}
}
}
}).forEach(function(item) {
for (i = 0; i != item.things.length; ++i)
{
item.things[i].upper_appendage = item.things[i].arm;
delete item.things[i].arm; ;
}
db.items.update({
_id: item._id
}, item);
})
note: i've assumed you want to make all records have upper_appendageand get rid of 'arm' field. if it's the other way you want, just switch things around.

mongoDB collection.findOne() update the query with its own results

I have a query like this one :
.findOne( {
_id: myObjectId,
}, {
fields: {
smallSingleValue: 1,
HUDGE_OBJECT: 1,
}
} );
I do not need the entire HUDGE_OBJECT (it is roughly 1 Mo), I need HUDGE_OBJECT[ smallSingleValue ] ( less than a Ko ).
Right now, I can make that request and get the entire HUDGE_OBJECT, or make two requests ; one the guet the smallSingleValue and the other one to get the HUDGE_OBJECT[ smallSingleValue ].
Both solution are crapy.
Is there a way to do something like that :
fields: {
smallSingleValue: 1,
`HUDGE_OBJECT.${ $smallSingleValue }`: 1,
}
Obviously not with that syntax, but you get the idea.
I tried aggregation, but it’s probably not the solution.
Does the projection operator allows it ?
https://docs.mongodb.com/manual/reference/operator/projection/positional/
EDIT FOR THE COMMENTS :
Example of data :
{
_id: xxx,
firstName: xxx,
lastName: xxx,
currentLevel: bar, // <- that one is important
progress: {
foo: { big object },
bar: { big object },
baz: { big object },
...
}
}
What I need :
{
firstName: xxx,
lastName: xxx,
currentLevel: bar,
progress: {
bar: { big object },
}
}
But the question is : performance wise, is it better to just get the entire object (easy query) or to get a truncated object (more complex query but passing a bigger object) ? There are 50 «levels».
I don’ remember what I tried with the aggregation :x but it seemed to be a bad idea.

Cannot access mongoDB object in array - returns undefined

I have a very big problem when im trying to access objects in array in mongoDB.
First I'm finding where id key has a value of "mens" in my database collection "categories":
mongodb.db().collection("categories").find({id: "mens"}).toArray(function(err, data) {
console.log(data);
}
When i try to output the result in the console, it shows me this :
[ { _id: 5172d1daffdd81f3234d5f88,
categories: [ [Object], [Object] ],
id: 'mens',
name: 'Mens',
page_description: 'Men\'s range. Hard-wearing boots, jackets and clothing for unbeatable comfort day in, day out.
headed.',
page_title: 'Men\'s Footwear, Outerwear, Clothing & Accessories',
parent_category_id: 'root',
c_showInMenu: true } ]
But when I try to get for example name or page_title with this :
mongodb.db().collection("categories").find({id: "mens"}).toArray(function(err, data) {
console.log(data.page_title);
}
It returns UNDEFINED ! ! !
The data returned is an array, so you need to access the object in the array as data[0].page_title i.e.
mongodb.db().collection("categories").find({id: "mens"}).toArray(function(err, data) {
console.log(data[0].page_title); // prints "Men's Footwear, Outerwear, Clothing & Accessories"
}

How can I access a date typed field from an ExtJS JSonStore?

I've been trying to retrieve a date value and an integer value from the database, using the following code:
var l_alsChampsMois, l_stoDonneesMois;
try {
l_alsChampsMois = [
{name: "date_mois", type: "date", dateFormat: "Y-m-d"},
{name: "indice", type: "integer"}
];
l_stoDonneesMois = new Ext.data.JsonStore({
fields: l_alsChampsMois,
autoLoad: false,
proxy: {
type: "ajax",
url: "/commun/req_sql/req_ind_per_mois.php",
reader: {
type: "json",
root: "rows"
},
// some configs to use jsFiddle echo service (you will remove them)
actionMethods: {
read: "POST"
},
extraParams: {
key:"test"
}
},
listeners: {
load: function(objStore, alsLignes, blnOk, objOptions) {
window.alert("Mois fin : " + objStore.getAt(0).get("date_mois"));
}
}
});
l_stoDonneesMois.load({params: {
p_idsoc: l_strIdSociete,
p_mois: l_datDebut.getMonth() + 1,
// getMonth renvoie 0 pour janvier, etc.
p_annee: l_datDebut.getFullYear(),
p_debut: 1,
p_etape: 1
}
});
with l_strIdSociete and l_datDebut being variables previously assigned and /commun/req_sql/req_ind_per_mois.php the PHP page that retrieves the data and converts it to JSON.
It seems to work fine (indeed, Firebug tells me the load does retrieve a data structure with "date_mois" and "indice" containing the values I expect them to), only the window.alert returns undefined. If I replace "date_mois" with "indice", it returns the expected value for "indice".
I've tried to use objStore.getAt(0).getData()["date_mois"], to no avail.
My only clue about this is that "date_mois" in the data structure shown by Firebug is an Object, but even so it shouldn't be undefined, now should it? I looked up http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Field-cfg-type that wasn't exactly forthcoming with straight answers.
So what did I do wrong there?
If you need current time you can use php time function(note: it returns seconds, JS uses milliseconds), in another case you need to convert by mktime function.

Parsing JSON ( again ) in iOS

I'm just playing with the JSON parser in iOS it's working fine as a ( simple ) example . But I was wonder how one would actually parse something (a bit) more complicated, the a Twitter trends JSON, like this :
{
"trends": {
"2011-03-13 11:42:17": [
{
"events": null,
"query": "Fukushima",
"promoted_content": null,
"name": "Fukushima"
},
{
"events": null,
"query": "Rebecca Black",
"promoted_content": null,
"name": "Rebecca Black"
},
{
"events": null,
"query": "Pearl Harbour",
"promoted_content": null,
"name": "Pearl Harbour"
},
...
{
"events": null,
"query": "Magdalena Neuner",
"promoted_content": null,
"name": "Magdalena Neuner"
}
]
},
"as_of": 1300016537
}
How would one just return the first 3 queries ? in this instance : Fukushima, Rebecca Black and Pearl Harbour .
Using the example code, it goes something like this :
for (int i = 0; i < [luckyNumbers count]; i++)
[text appendFormat:#"%#\n", [luckyNumbers objectAtIndex:i]];
This is for a much simpler feed though, can it be approached the same way for what I'm looking for ?
I'm trying to return the value of "query":
So I`m doing this :
NSLog(#"%#", [[luckyNumbers objectForKey:#"trends"]);
This of course logs the content of the key "trend", how do I go about returning not only the first ( and only ) key of trends but also dig one more level down to return the content of "query" ??
I've also tried something like this :
NSString *date = [[[luckyNumbers valueForKeyPath:#"trends"] allKeys] description];
NSArray *trends = [luckyNumbers objectForKey:#"trends"];
NSLog(#"%#", [trends valueForKeyPath:date]);
but no go ...
EDIT (aftet honcheng's answer):
Because I want to iterate through the results of "trends", I'm doing :
NSDictionary *luckyNumbers = [responseString JSONValue];
NSArray *keys = [[luckyNumbers objectForKey:#"trends"] allKeys];
for (int i =0; i < [keys count]; i++) {
NSLog(#"%#", [keys objectAtIndex:i]);
}
Obviously something is wrong because I'm not getting any result ..
JSON parser usually returns native NSObjects such as NSDictionary and NSArray. After parsing, you just have to treat it like a new object.
[luckyNumbers allKeys] returns an NSArray ["trends", "as_of"]
[[luckyNumbers objectForKey:#"trends"] allKeys"] returns an NSArray ["2011-03-13 11:42:17"]
Since allKeys returns an NSArray, you can just use a for loop to get all your keys.