define parent in elasticsearch-dsl-py - python

I'm trying to use Elasticsearch-dsl-py to index some data from a jsonl file with many fields. ignoring the less general parts, the code looks like this:
es = Elasticsearch()
for id,line in enumerate(open(jsonlfile)):
jline = json.loads(line)
children = jline.pop('allChildrenOfTypeX')
res = es.index(index="mydocs", doc_type='fatherdoc', id=id, body=jline)
for ch in children:
res = es.index(index="mydocs", doc_type='childx', parent=id, body=ch)
trying to run this ends with the error:
RequestError: TransportError(400, u'illegal_argument_exception', u"Can't specify parent if no parent field has been configured")
I guess I need to tell es in advance that has a parent. However, what I don't want is to map ALL the fields of both just to do it.
Any help is greatly welcomed!

When creating your mydocs index, in the definition of your childx mapping type, you need to specify the _parent field with the value fatherdoc:
PUT mydocs
{
"mappings": {
"fatherdoc": {
"properties": {
... parent type fields ...
}
},
"childx": {
"_parent": { <---- add this
"type": "fatherdoc"
},
"properties": {
... parent type fields ...
}
}
}
}

Related

SQLAlchemyObjectType.Meta two models graphene

I am trying to combine two SQLAlchemyConnectionField. The current error i face is graphql.error.base.GraphQLError: Expected value of type "PostsObject" but got: Tag
My current connections are defined like so posts = SQLAlchemyConnectionField(PostsObject.connection, /* input arguments like posts(name: "") */) Is there a way to add another type or allow to return something like
"data": {
"posts": {
"edges": [
{
"node": "Different table"
},
{
"node": "Other table"
}]}},
I am using graphene_sqlalchemy well anyway thats all thanks !

Django adding data into model from nested json returning TypeError: 'NoneType' object is not subscriptable

I am using a third-party API to get data and add it into my database via objects.update_or_create() method. This data has many records and some of the fields in the response only exists for certain records.
Below the a snippet of the JSON that is returned from the API. However this data is only present for some of the records in the JSON response. When I try to add this data into my model, I am getting the following error:
'f_name': i.get('card_faces')[0].get('name'),
TypeError: 'NoneType' object is not subscriptable
I am trying to have it so that if the card_faces field exists, True is added to the card_face column in the database, and then the card_faces name to the database. If card_faces doesn't exist, then False is added to the card_face column in the database, and subsequent fields are null.
JSON:
{
"data": [
{
"name": "Emeria Captain"
},
{
"name": "Emeria's Call // Emeria, Shattered Skyclave",
"card_faces": [
{
"object": "card_face",
"name": "Emeria's Call"
},
{
"object": "card_face",
"name": "Emeria, Shattered Skyclave"
}
]
}
]
}
views.py:
for i in card_data:
Card.objects.update_or_create(
id=i.get('id'),
defaults={
'name': i.get('name'),
'card_faces': i.get('card_faces'),
'f_name': i.get('card_faces')[0].get('name'),
'b_name': i.get('card_faces')[1].get('name'),
}
)
If the card_faces field doesn't exist, then the result of .get('card_faces') will be None, which you can't then call index 0 on
Break apart your line and do a logic check instead - this solution assumes that if card_faces does exist, there will be an index 0 and 1; you haven't provided enough information to assume otherwise
card_faces = i.get('card_faces')
f_name = None
b_name = None
if card_faces:
f_name = card_faces[0].get('name')
b_name = card_faces[1].get('name')
defaults = {
'name': i.get('name'),
'card_faces': True if card_faces else False,
'f_name': f_name,
'b_name': b_name,
}

How to accept None for String type field when using Flask-RESTPlus

I am just starting develop with flask-restplus and I am not a native speaker,
but I will try to describe my question as clear as I can.
I know there is a fields module in flask that help us define and filter response data type,
such as String, Integer, List and so on.
Is there any way to allow NULL / None when using fields module?
the following is my code that using field module to catch the value,
add_group = api.model(
"add_group",
{"team_groups": fields.List(fields.Nested(api.model("team_groups", {
"name": fields.String(example="chicago bulls", description="name of add group"),
"display_name": fields.String(example="bulls", description="display name of add group")})))})
and if the data type of display_name is not String, there would be the following error raised,
{
"errors": {
"team_groups.0.display_name": "123 is not of type 'string'"
},
"message": "Input payload validation failed"
}
what I want is when entering display_name, I can enter bulls or None
It seems few of the reference data / questions can be found, and I only found one result related
to my question, but eventually converting as non-null value to solve the issue.
if there is any part of my question not much clear,
please let me know, thank you.
the following is my develop environment:
flask-restplus 0.13.0
Python 3.7.4
postman 7.18.1
The following is my updated code:
from flask_restplus import Namespace, fields
class NullableString(fields.String):
__schema_type__ = ['string', 'null']
__schema_example__ = 'nullable string'
class DeviceGroupDto:
api = Namespace("device/group", description="device groups")
header = api.parser().add_argument("Authorization", location="headers", help="Bearer ")
get_detail_group = api.model(
"getdetail",
{"team_groups": fields.List(fields.String(required=True,
description="team group id to get detail", example=1))})
add_group = api.model(
"add_group",
{"team_groups": fields.List(fields.Nested(api.model("team_groups", {
"name": fields.String(example="chicago bulls", description="name of add group"),
"display_name": NullableString(attribute='a')})))})
if I input the following payload: (by postman)
{
"team_groups": [
{
"name": "chicago bulls",
"display_name": null
}
]
}
It still returns:
{
"errors": {
"team_groups.0.display_name": "None is not of type 'string'"
},
"message": "Input payload validation failed"
}
Yes, you can create a child class and use it instead of default ones, which will accept None as well
class NullableString(fields.String):
__schema_type__ = ['string', 'null']
__schema_example__ = 'nullable string'
So your code will look like
{ "property": NullableString(attribute=value)}
Additionally you can visit the issue github.com/noirbizarre/flask-restplus/issues/179
if some of your fields are optional then make required=False
add_group = api.model(
"add_group",
{"team_groups": fields.List(fields.Nested(api.model("team_groups", {
"name": fields.String(example="chicago bulls", description="name of add group"),
"display_name": fields.String(example="bulls", description="display name of add group", required=False)})))})
Here's slightly evolved approach that I use. It lets you have fields of any type as nullable.
def nullable(fld, *args, **kwargs):
"""Makes any field nullable."""
class NullableField(fld):
"""Nullable wrapper."""
__schema_type__ = [fld.__schema_type__, "null"]
__schema_example__ = f"nullable {fld.__schema_type__}"
return NullableField(*args, **kwargs)
employee = api.model(
"Employee",
{
"office": nullable(fields.String),
"photo_key": nullable(fields.String, required=True),
},
)

Graphene-django - How to catch response of query?

I use django and django graphene for make a graphql API.
In the view of my application, I use reactJS and react-bootstrap-table. React-bootstrap-table expects that I pass it an object array but does not support nested objects.
I created query in my schema.py:
class ApplicationNode(DjangoObjectType):
class Meta:
model = Application
filter_fields = ['name', 'sonarQube_URL']
interfaces = (relay.Node,)
class Query(ObjectType):
application = relay.Node.Field(ApplicationNode)
all_applications = DjangoFilterConnectionField(ApplicationNode)
The answers to these queries are JSON nested objects like this:
{
"data": {
"allApplications": {
"edges": [
{
"node": {
"id": "QXBwbGljYXRpb25Ob2RlOjE=",
"name": "foo",
"sonarQubeUrl": "foo.com",
"flow":{
"id": "QYBwbGljYXRpb45Ob2RlOjE=",
"name": "flow_foo"
}
}
},
{
"node": {
"id": "QXBwbGljYXRpb25Ob2RlOjI=",
"name": "bar",
"sonarQubeUrl": "bar.com"
"flow":{
"id": "QXBwbGljYXRpb26Ob2RlOjA=",
"name": "flow_bar"
}
}
}
]
}
}
}
I have to put them flat before giving them to React-bootstrap-table.
What is the better way, intercept the results of graphene-django queries to put them flat or make this job in ReactJS view?
If the first way is better, how to intercept the results of graphene-django queries to put them flat?
The best thing to do is to wrap react-bootstrap-table in a new component. In the component massage the relay props into a flat structure as needed for react bootstrap table.
For example:
MyReactTable = ({allApplications}) => {
let flatApplications = allApplications.edges.map(({node: app}) => {
return {
name: app.name,
sonarQubeUrl: app.sonarQubeUrl,
flowName: app.flow.name
};
});
return (
<BootstrapTable data={flatApplications} striped={true} hover={true}>
<TableHeaderColumn dataField="name" isKey={true} dataAlign="center" dataSort={true}>Name</TableHeaderColumn>
<TableHeaderColumn dataField="sonarQubeUrl" dataSort={true}>Sonar Qube Url</TableHeaderColumn>
<TableHeaderColumn dataField="flowName" dataFormat={priceFormatter}>Flow Name</TableHeaderColumn>
</BootstrapTable>
);
};

django tastypie get related column total amount

Given the below JSON result from tastypie, I would like to create a new value at check.payments_total which is equal to the total amount of the payments (in this case, 44.00). Any clue on how to do this? I'm completely stumped. payments is a joined foreign key to the check table.
{
"objects": [
{
"check": {
"id": "58a81b36-1ea6-403b-9902-a50cbd13cf2e",
"number": 2,
"payments": [
{
"amount": "5.00",
},
{
"amount": "39.00",
}
]
}
}
]
}
If for the response, then you could override the following method in your resource (the snippet is from tastypie.resources.Resource):
def alter_list_data_to_serialize(self, request, data):
"""
A hook to alter list data just before it gets serialized & sent to the user.
Useful for restructuring/renaming aspects of the what's going to be
sent.
Should accommodate for a list of objects, generally also including
meta data.
"""
return data
just include something like (not tested, consider to be pseudo-code):
total_amount = 0.0
for object in data[ 'objects' ]:
total_amount += object[ 'amount' ]
return { 'objects' : data[ 'objects' ], 'total_amount' : total_amount }
and you should be done.

Categories