I'm using Python and trying to access some items in a list within a dictionary. I do not need to loop, just need the item value. Please see this:
<pre>
BROKER_INFO = {'AMERITRADE': {
'file_info': {
'broker_name' : 'TD Ameritrade',
'filename' : 'ameritrade',
'row_start' : '1',
'active' : 'Y',
'actions' : 'Bought,Sold',
'buy' : 'Bought',
'sell' : 'Sold',
'columns' : [
{'date': '0', 'action': '2', 'ticker': '4'}]
}
</pre>
I'm looking to get the value to "date", "action", "ticker' within "columns", which is within "file_info" and "AMERITRADE".
I tried this: BROKER_INFO[p_broker]['file_info']['columns']['action'], but no luck.
Many many thanks!
Try
BROKER_INFO[p_broker]['file_info']['columns'][0]['action']
Related
I have a collection with structure somewhat like this :
{
"organization" : "Org1",
"active" : true,
"fields" : [
{
"key" : "key1",
"value" : "table"
},
{
"key" : "key2",
"value" : "Harrison"
}
]
}
I need to find all documents with organization : "Org1", active : true, and regex match the 'value' in fields.
In mongo shell, it works perfectly. I tried the query:
db.collection.find({"organization" : "Org1", "active" : true, "fields" : {$elemMatch : {"key" : "key2","value" : {$regex : /iso/i}}}}).pretty()
But when I tried to convert it to a Java code with Spring, it gives wrong results.
1. This one will give documents even if it didn't match the pattern:
#Query("{'organization' : ?0, 'active' : true, 'fields' : {$elemMatch : {'key' : ?1, 'value' : {$regex : ?2}}}}")
List<ObjectCollection> findFieldDataByRegexMatch(String org, String key, String pattern);
This one doesn't give any documents even though it should.
MongoTemplate MONGO_TEMPLATE = null;
try {
MONGO_TEMPLATE = multipleMongoConfig.secondaryMongoTemplate();
} catch (Exception e) {
e.printStackTrace();
}
List<Criteria> criteriaListAnd = new ArrayList<Criteria>();
Criteria criteria = new Criteria();
String pattern = "/iso/i";
criteriaListAnd.add(Criteria.where("organization").is("Org1"));
criteriaListAnd.add(Criteria.where("active").is(true));
criteriaListAnd.add(Criteria.where("fields").elemMatch(Criteria.where("key").is(key).and("value").regex(pattern)));
criteria.andOperator(criteriaListAnd.toArray(new Criteria[criteriaListAnd.size()]));
Query query = new Query();
query.addCriteria(criteria);
List<ObjectCollection> objects = MONGO_TEMPLATE.find(query, ObjectCollection.class);
What am I missing here and how should I form my query?
You are making a very small mistake, in the pattern you are passing / which is the mistake, it took me half an hour to identify it, finally, I got it after enabling the debug log of spring boot.
For the first query, it should be called as below:
springDataRepository.findFieldDataByRegexMatch("Org1", "key2", "iso")
And the query should be modified in the Repository as to hanlde the case sensetivity:
#Query("{'organization' : ?0, 'active' : true, 'fields' : {$elemMatch : {'key' : ?1, 'value' : {$regex : ?2, $options: 'i'}}}}")
List<Springdata> findFieldDataByRegexMatch(String org, String key, String pattern);
The same issue in your second query also, just change String pattern = "/iso/i"; to String pattern = "iso" or String pattern = "iso.*" ;
Both will start working, For details please check the my GitHub repo https://github.com/krishnaiitd/learningJava/blob/master/spring-boot-sample-data-mongodb/src/main/java/sample/data/mongo/main/Application.java#L60
I hope this will resolve your problem.
I have an initialized dictionary like:
nemas = {'PERSON' : '', 'ORGANIZATION':'' , 'LOCATION': ''}
and three lists of names :
person_names = [u'Albert Einstein', u'Hermann Einstein', u'Pauline Koch', u'Einstein', u'Jakob']
organization_names = [u'Elektrotechnische Fabrik J. Einstein & Cie']
location_names = [u'Ulm', u'Kingdom of Britain', u'Munich']
I intend to update the dictionary and get:
names = { 'PERSON' : [u'Albert Einstein', u'Hermann Einstein', u'Pauline Koch', u'Einstein', u'Jakob'],
'ORGANIZATION': [u'Elektrotechnische Fabrik J. Einstein & Cie'],
'LOCATION': [u'Ulm', u'Kingdom of Britain', u'Munich'] }
I tried :
name_dict = {"PERSON":dict(person_names), "ORGANIZATION": dict(organization_names), "LOCATION":dict(locatoin_names)}
print(names.update(name_dict))
but it didn't work. Is there any Pythonic way to solve this problem?
Let's say we ignore your first line:
nemas = {'PERSON' : , 'ORGANIZATION': , 'LOCATION': }
You simply can't do that. However you could do
nemas = {'PERSON' : None, 'ORGANIZATION': None, 'LOCATION': None}
Then in the end what you want is a dictionary of lists but you try to make a dict of dicts. Try this:
name_dict = {"PERSON":person_names, "ORGANIZATION": organization_names, "LOCATION":location_names}
Please note that I fixed some typos.
Then you can get the expected output by
print(name_dict)
I'm looking for a versatile way to translate a big object into a custom object using a template. It should be able to traverse each value of arrays, and reference parent values in the loop.
Imagine an object like:
{
collectionId : 432,
products : [
{
productId : 1155,
suppliers : [
{
supplierId : 252,
supplier : 'SupplyCompany',
shipments : [
{
date : 'foo',
order : 'bar',
id : 45
},
{},
{},
//...
]
},
{},
{},
//...
]
},
{},
{},
//...
],
}
I would for example want to flatten this into:
[
{
collectionId : 432,
productId : 1155,
supplierId : 252,
supplier : 'SupplyCompany',
date : 'foo',
order : 'bar',
id : 45
},
{},
{},
//...
]
Right now I'm using manual for for for loops, but this isn't very versatile when the source object changes or one of my output objects change. It's not very maintainable to 'hardcode' these translations.
There are templating engines that do something resembling what I want, e.g. JsRender. It theoretically allows you to do what I need:
{{for products}}
{{for suppliers}}
{{for shipments}}
collectionId : {{:#parent.parent.parent.parent.data.collectionId}}
productId : {{:#parent.parent.parent.data.productId}},
supplierId : {{:#parent.parent.data.supplierId}},
supplier : {{:#parent.parent.data.supplier}},
date : {{:date}},
order : {{:order}},
id : {{:id}
{{/for}}
{{/for}}
{{/for}}
(This is pretty nice because Mustache doesn't allow you to do this.)
However, jsRender reads strings (templates) and output strings (html). The overhead from all the stringify and parse is not doing any good in my case.
I'm looking for something that does this kind of processing with objects. From objects to objects.
There are a few ways you can do that kind of thing using JsRender. For example it is really easy to create custom tags, converters, etc. (or use helper functions) and make them have side effects of mapping objects to some output object. Of course the philosophy of JsRender is generally to be declarative, without side effects, but if you want to you can indeed use it a 'processor'.
Here is a jsfiddle sample which can give you some ideas:
It uses a custom tag:
$.views.tags({
addObject: function(target) {
var item = $.extend({}, this.tagCtx.props);
target.push(item);
...
}
})
and a template:
{{for products ~collectionId=collectionId}}
{{for suppliers ~productId=productId}}
{{for shipments ~supplierId=supplierId ~supplier=supplier}}
{{addObject ~target collectionId=~collectionId productId=~productId supplierId=~supplierId supplier=~supplier date=date order=order id=id/}}
{{/for}}
{{/for}}
{{/for}}
Firstly, I will be using ember-cli for development and I get JSON from the server in embedded format:
Single Objects
{
"id" : 1,
"name" : "Tom",
"surname" : "Smith",
"address" : {
"id" : 2,
"street" : "23",
"city" : "...",
...
}
}
Arrays
[
{
"id" : 1,
"name" : "Tom",
"surname" : "Smith",
"address" : {
"id" : 2,
"street" : "23",
"city" : "...",
...
}
},
{
"id" : 2,
"name" : "Tom",
"surname" : "Smith",
"address" : {
"id" : 4,
"street" : "23",
"city" : "...",
...
}
},
...
]
I have worked out how to append the prefix onto each payload using the following in RestAdapter.
export default DS.RESTSerializer.extend({
extract : function(store, type, payload, id, requestType) {
var typeKey = type.typeKey,
typeKeyPlural = typeKey.pluralize();
//Add name of model to payload as expected by ember data
var modelName = Array.isArray(payload) ? typeKeyPlural : typeKey;
var normalizedPayload = {};
normalizedPayload[modelName] = payload;
return this._super(store, type, normalizedPayload, id, requestType);
},
)}
I have searched around all over the place and can see all these different ways of embedding records in ember.
The official docs say to us the DS.EmbeddedRecordsMixin Class. But this would mean I would need to create a DS.ActiveModelSerializer for every single model, I would rather define the attribute in the model itself {embedded : "always"}.
http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html
This actually sort of worked but is obviously old because the parameters have since changed. It is a bit of a hack in my opinion.
http://mozmonkey.com/2013/12/serializing-embedded-relationships-ember-data-beta/
There is this project, but no docs or example of how to get it working.
https://github.com/pixelhandler/ember-data-extensions
All in all I am very confused.
The correct approach is to use a serializer and the DS.EmbeddedRecordsMixin.
You are really fighting against separation of concerns by specifying serializer options in your models.
So, that said, lets get down to the evil.
You can simply copy DS.EmbeddedRecordsMixininto your application and modify the way it checks its options to instead examine the relationship meta data on the model type. You can then extendyour default ApplicationSerializer with your custom mixin so that you don't have to specify a serializer for all your models.
You will need to modify the following function, from this:
attrsOption: function(attr) {
var attrs = this.get('attrs');
return attrs && (attrs[camelize(attr)] || attrs[attr]);
}
To something like this (note the extra param):
attrsOption: function(attr, type) {
var meta = type.metaForProperty(attr) || type.metaForProperty(camelize(attr));
return meta && meta.options;
}
You will also need to modify all the callers of attrsOption to pass the model type down, but you will then have your very own embedded record mixin that gets its options from the model type.
Then when specifying your model relationships you can use the embedded record options as follows:
address: DS.belongsTo('address', { embedded: 'always' })
I am trying to combine regex and embedded object queries and failing miserably. I am either hitting a limitation of mongodb or just getting something slightly wrong maybe someone out ther has encountered this. The documentation certainly does'nt cover this case.
data being queried:
{
"_id" : ObjectId("4f94fe633004c1ef4d892314"),
"productname" : "lightbulb",
"availability" : [
{
"country" : "USA",
"storeCode" : "abc-1234"
},
{
"country" : "USA",
"storeCode" : "xzy-6784"
},
{
"country" : "USA",
"storeCode" : "abc-3454"
},
{
"country" : "CANADA",
"storeCode" : "abc-6845"
}
]
}
assume the collection contains only one record
This query returns 1:
db.testCol.find({"availability":{"country" : "USA","storeCode":"xzy-6784"}}).count();
This query returns 1:
db.testCol.find({"availability.storeCode":/.*/}).count();
But, this query returns 0:
db.testCol.find({"availability":{"country" : "USA","storeCode":/.*/}}).count();
Does anyone understand why? Is this a bug?
thanks
You are referencing the embedded storecode incorrectly - you are referencing it as an embedded object when in fact what you have is an array of objects. Compare these results:
db.testCol.find({"availability.0.storeCode":/x/});
db.testCol.find({"availability.0.storeCode":/a/});
Using your sample doc above, the first one will not return, because the first storeCode does not have an x in it ("abc-1234"), the second will return the document. That's fine for the case where you are looking at a single element of the array and pass in the position. In order to search all of the objcts in the array, you want $elemMatch
As an example, I added this second example doc:
{
"_id" : ObjectId("4f94fe633004c1ef4d892315"),
"productname" : "hammer",
"availability" : [
{
"country" : "USA",
"storeCode" : "abc-1234"
},
]
}
Now, have a look at the results of these queries:
PRIMARY> db.testCol.find({"availability" : {$elemMatch : {"storeCode":/a/}}}).count();
2
PRIMARY> db.testCol.find({"availability" : {$elemMatch : {"storeCode":/x/}}}).count();
1