MongoEngine delete nested embedded document? - python

I have a collection with en embedded document that has a list of embedded documents and need to be able to delete alert_list index [x] but have not been able to craft a pull command that works. Here my model structure:
class Alert(medb.EmbeddedDocument):
name = medb.StringField(default = 'new alert')
class Sensor(medb.EmbeddedDocument):
name = medb.StringField(default='')
alert_list = medb.ListField(medb.EmbeddedDocumentField(Alert), default=Alert)
class SiteConfig(medb.Document):
name = medb.StringField(default = 'name')
sensordict = medb.MapField(medb.EmbeddedDocumentField(Sensor))
#delete alert_item #2 for sensordict['99']
SiteConfig.objects(id=siteid).update_one(pull__ ????? what goes here???
I can do it in pymongo like this ( and it works just fine):
#load site into pymongo
pysite = pydb.db.SiteConfig.find_one({'_id': ObjectId(siteid)})
#delete the alert
del pysite['sensordict'][sensorid]['alert_list'][alertindex]
#save modified Site back to db
pydb.db.SiteConfig.replace_one({'_id': ObjectId(siteid)}, pysite, upsert=True)
But would prefer to use MongoEngine if possible. - any suggestions?
Thanks
Bill

Related

simple-salesforce - How to create Knowledge Page Layout programatically?

I've been able to create a Record Type and Custom Field for the Knowledge module of Salesforce with the metadata api implemented in simple-salesforce's python library, but when trying to create a Page Layout it throws an exception without much info on why is the creation failing (or at least I don't get it).
I'm trying to create the page layout in the following way:
def create_page_layout(self, layout_name, fields):
mdapi = self.sf.mdapi
# custom_layout_section = []
custom_layout_items = []
for field in fields:
custom_layout_items.append(mdapi.LayoutItem(
field=field
))
custom_layout_section = [mdapi.LayoutSection(
label='Information',
style='OneColumn',
layoutColumns=mdapi.LayoutColumn(
layoutItems=custom_layout_items
)
)]
custom_layout = mdapi.Layout(
fullName='Knowledge__kav.' + layout_name + '__c',
layoutSections=custom_layout_section
)
mdapi.Layout.create(custom_layout)
The param layout_name contains 'TestDefaultPL'.
The param fields contains ['Title', 'UrlName'].
The exception: Exception: Knowledge__kav.TestDefaultPL__c: (FIELD_INTEGRITY_EXCEPTION, Parent entity failed to deploy).
The docs about this object: link.
As an example, I was able to create a custom field for the Knowledge module in the following way:
def create_custom_field(self, name):
mdapi = self.sf.mdapi
# TODO: Field permissions
custom_field = mdapi.CustomField(
label=name, # Field label
fullName='Knowledge__kav.' + name + '__c', # Field name (format has to be CustomObject.FieldName)
type=mdapi.FieldType("LongTextArea"),
length=32000,
description='Default Rich Text Area',
visibleLines=25
)
return mdapi.CustomField.create(custom_field)
Could someone help me with this problem about the Page Layout creation?

How can you query embedded document that is null with mongoengine

I am new to mongoengine and querying. I got a document and an embedded document that looks like the following:
class Plan(EmbeddedDocument):
name = StringField()
size = FloatField()
class Test(Document):
date = DateTimeField()
plan = EmbeddedDocumentField(Plan)
How Can I get all Test-Documents that have no size set. That means that size=null/None?
I tried it with __raw__ query, but this did not work for me..
The way to query attribute of nested/embedded documents is done in the following manner (doc):
class LightSaber(EmbeddedDocument):
color = StringField()
length = FloatField()
class Jedi(Document):
name = StringField()
light_saber = EmbeddedDocumentField(LightSaber)
saber1 = LightSaber(color='red', length=32)
Jedi(name='Obiwan', light_saber=saber1).save()
saber2 = LightSaber(color='yellow', length=None)
Jedi(name='Yoda', light_saber=saber2).save()
Jedi(name='Rey', light_saber=None).save()
for jedi in Jedi.objects(light_saber__length=None):
print(jedi.name)
# prints:
# Yoda
# Rey
That being said, by naming your attribute "size", you are hitting an edge case. In fact "size" is a mongoengine operator and so if you query Test.objects(plan__size=None), you'll get an error because MongoEngine believes that you want to make use of the size operator.
To do the same with __raw__, you need to use the following:
for jedi in Jedi.objects(__raw__={'light_saber.length': None}):
print(jedi.name)
Using __raw__ works fine with "size" as well, in your example that would be: Test.objects(__raw__={'plan.size': None})

Why is it so slow when update ListField in mongoengine?

It's too slow when I update a ListField with mongoengine.Here is an example
class Post(Document):
_id = StringField()
txt = StringField()
comments = ListField(EmbeddedDocumentField(Comment))
class Comment(EmbeddedDocument):
comment = StringField()
...
...
position = 3000
_id = 3
update_comment_str = "example"
#query
post_obj = Post.objects(_id=str(_id)).first()
#update
post_obj.comments[position].comment = update_comment_str
#save
post_obj.save()
The time it cost increases with the increase of the length of post_obj.comments.
How to optimize it?
Post.objects(id=str(_id)).update(**{"comments__{}__comment".format(position): update_comment_str})
In your code.
You fetched the whole document into python instance which will take place in RAM.
Then update 3000 th comments which will do some magic in mongoengine(marking changed fields and so on).
Then saves document.
In my answer,I have sent the update instruction to mongodb instead of fetching whole documents with N comments into Python which will save memory(RAM) and time.
The mongoengine/MongoDB supports index support update like
set__comments__1000__comment="blabla"
In order to give position using variable, I've used python dictionary and kwargs trick.

mongengine (.10.6) does not save the Document

I have simple REST/json api. I am trying to update a mongoengine model Listing using a PUT call. I get one from the mongodb and update it using my own deserilize method with the incoming json. The update does not work as the json has a few DBRef and EmbeddedDocuments. The object does get updated with the correct values before the save is executed. There is no error but the object does not get saved. Any thoughts?
obj = Listing.objects.get(pk=id)
obj.deserialize(**request.json)
obj.save()
obj.reload()
return obj
class Listing():
name = db.StringField()
l_type = db.StringField( choices=listing_const.L_TYPE.choices(), )
expiry = db.ComplexDateTimeField( auto_now=False,auto_now_add=False, )
a_data = db.EmbeddedDocumentField(Media)
lcrr = db.ReferenceField( 'LCRR', reverse_delete_rule=3, dbref=False, )
meta = {
'db_alias': config.get_config()['MONGODB_SETTINGS']['alias'],
'cascade':True
}

Google App Engine: defining custom id and querying

I want to define a custom string as an ID so I created the following Model:
class WikiPage(ndb.Model):
id = ndb.StringProperty(required=True, indexed=True)
content = ndb.TextProperty(required=True)
history = ndb.DateTimeProperty(repeated=True)
Based on this SO thread, I believe this is right.
Now I try to query by this id by:
entity = WikiPage.get_by_id(page) # page is an existing string id, passed in as an arg
This is based on the NDB API.
This however isn't returning anything -- entity is None.
It only works when I run the following query instead:
entity = WikiPage.query(WikiPage.id == page).get()
Am I defining my custom key incorrectly or misusing get_by_id() somehow?
Example:
class WikiPage(ndb.Model):
your_id = ndb.StringProperty(required=True)
content = ndb.TextProperty(required=True)
history = ndb.DateTimeProperty(repeated=True)
entity = WikiPage(id='hello', your_id='hello', content=...., history=.....)
entity.put()
entity = WikiPage.get_by_id('hello')
or
key = ndb.Key('WikiPage','hello')
entity = key.get()
entity = WikiPage.get_by_id(key.id())
and this still works:
entity = WikiPage.query(WikiPage.your_id == 'hello').get()

Categories

Resources