Update document with pyarango - python

I have an existing arango document that I get from a key:
doc = collection[key]
I used to update using:
for key, value in new_data.item():
doc[key] = value
doc.save()
Sometime, new_data has an empty field and I want to remove this field from the doc.
I must miss something, since nothing I tried seems to work:
doc.patch(keep_null=True, **new_data)
doc.patch(keep_null=False, **new_data)
doc.set(new_data)
I tried with set() and getStore() too (when new_data is an arango doc)
I wanted to iterate on doc keys (using getStore), but I don't know how to delete a field from a doc...
How do I replace doc data by "new data" (which is an arango doc with same _key/_id)? Any help is appreciated!

Was trying to figure out how to do this earlier today. What you need to do is
del arangodoc["key"]
arangodoc.save()#the save is important, patch won't delete the missing field.

Related

How to open a document from a Notes View with python noteslib?

I have an established connection with a notes database and I am able to loop through all the records in a view. What I am curious about if it is possible to open a document and get the data from it using python. (Like double clicking on a record from an HCL Notes Client).
Here is my code simplified:
import noteslib
db = noteslib.Database('my-domino-server','my-db.nsf', 'mypassword')
view = db.GetView('my_view')
doc = view.GetFirstDocument()
while doc:
print(doc.ColumnValues)
#here after printing the column values, I want to open the document and store it's values in a variable.
doc = view.GetNextDocument(doc)
I tried googling about LotusScript and I found the Open() method, but doc.Open() did not work.
Just use the LotusScript documentation to find examples for everything you need.
In your case you start with the NotesDatabase - class, then get an object of type NotesView and finally get a NotesDocument object.
This doc object does not need to be opened. You can directly access all items in that document either by their name or -if you don't know the name- by cycling through all items.
If you e.g. know the name of an item (can be found in the document properties box on the second tab, found with Alt + Enter) then you can read the value like this:
#Subject of a given mail
subject = doc.GetitemValue( "Subject" )[0]
#Start date of a calendar entry
startdate = doc.GetItemValue( "StartDate" )[0]
# cycle through all items
for item in doc.Items
print(item.Name)
value = item.Values
Take care: items are always arrays, even if they contain only a single value. To get the value of a single value item, always access the element at position 0.

How to update a field in a Firestore document only if it exists (using Python)?

Firestore documentation explains you can use doc_ref.update({'key': 'value'}) to update a single field in a document (and create it if that field doesn't exist).
The problem is: in my use case I don't want to create that field if it doesn't exist (would rather skip). Also if I do need to create it, doc_ref.set({'key': 'value'}, merge=True) will give what I want.
I found zero ready-to-use answer on the internet and wrote this Python code snippet for my own use case, and I'm sharing here for others to reuse.
Please read the comment to see how it works:
key = 'field'
key_nonexistent = 'field_nonexistent'
doc_ref = db.collection('test_coll').document('test_doc')
doc_ref.set({key: False})
# doc_ref.update({key_nonexistent: True}) # Will create 'field_nonexistent' -- not desired
dict_doc = doc_ref.get().to_dict()
if key in dict_doc.keys():
doc_ref.update(key: True) # Will update the field only if it exists -- desired
if key_nonexistent in dict_doc.keys():
doc_ref.update(key_nonexistent: not dict_doc[key_nonexistent]) # Proves the field won't be created if not existent. You can uncomment/comment out the commented line above to see how the result changes

Get fields from a specific Jira issue

I'm trying to get all the fields and values from a specific issue my code:
authenticated_jira = JIRA(options={'server': self.jira_server}, basic_auth=(self.jira_username, self.jira_password))
issue = authenticated_jira.issue(self.id)
print issue.fields()
Instead of returning the list of fields it returns:
<jira.resources.PropertyHolder object at 0x108431390>
authenticated_jira = JIRA(options={'server': self.jira_server}, basic_auth=(self.jira_username, self.jira_password))
issue = authenticated_jira.issue(self.id)
for field_name in issue.raw['fields']:
print "Field:", field_name, "Value:", issue.raw['fields'][field_name]
Depends on field type, sometimes you get dictionary as a value and then you have to find the actual value you want.
Found using:
print self.issue_object.raw
which returns the raw json dictionary which can be iterate and manipulate.
You can use issue.raw['fields']['desired_field'], but this way is kind of indirectly accessing the field values, because what you get in return is not consistent. You get lists of strings, then just strings themselves, and then straight up values that don't have a key for you to access them with, so you'll have to iterate, count the location, and then parse to get value which is unreliable.
Best way is to use issue.fields.customfield_# This way you don't have to do any parsing through the .raw fields
Almost everything has a customfield associated with it. You can pull just issues from REST API to find customfield #'s, or some of the fields that you get from using .raw will have a customfield id that should look like "customfield_11111" and that's what you'll use.
Using Answer from #kobi-k but dumping in better format, I used following code:
with open("fields.txt", "w") as f:
json.dump(issue.raw, f, indent=4)
It dumped all the fields in a file with name "fields.txt"

Add a field to existing document in CouchDB

I have a database with a bunch of regular documents that look something like this (example from wiki):
{
"_id":"some_doc_id",
"_rev":"D1C946B7",
"Subject":"I like Plankton",
"Author":"Rusty",
"PostedDate":"2006-08-15T17:30:12-04:00",
"Tags":["plankton", "baseball", "decisions"],
"Body":"I decided today that I don't like baseball. I like plankton."
}
I'm working in Python with couchdb-python and I want to know if it's possible to add a field to each document. For example, if I wanted to have a "Location" field or something like that.
Thanks!
Regarding IDs
Every document in couchdb has an id, whether you set it or not. Once the document is stored you can access it through the doc._id field.
If you want to set your own ids you'll have to assign the id value to doc._id. If you don't set it, then couchdb will assign a uuid.
If you want to update a document, then you need to make sure you have the same id and a valid revision. If say you are working from a blog post and the user adds the Location, then the url of the post may be a good id to use. You'd be able to instantly access the document in this case.
So what's a revision
In your code snippet above you have the doc._rev element. This is the identifier of the revision. If you save a document with an id that already exists, couchdb requires you to prove that the document is still the valid doc and that you are not trying to overwrite someone else's document.
So how do I update a document
If you have the id of your document, you can just access each document by using the db.get(id) function. You can then update the document like this:
doc = db.get(id)
doc['Location'] = "On a couch"
db.save(doc)
I have an example where I store weather forecast data. I update the forecasts approximately every 2 hours. A separate process is looking for data that I get from a different provider looking at characteristics of tweets on the day.
This looks something like this.
doc = db.get(id)
doc_with_loc = GetLocationInformationFromOtherProvider(doc) # takes about 40 seconds.
doc_with_loc["_rev"] = doc["_rev"]
db.save(doc_with_loc) # This will fail if weather update has also updated the file.
If you have concurring processes, then the _rev will become invalid, so you have to have a failsave, eg. this could do:
doc = db.get(id)
doc_with_loc = GetLocationInformationFromAltProvider(doc)
update_outstanding = true
while update_outstanding:
doc = db.get(id) //reretrieve this to get
doc_with_loc["_rev"] = doc["_rev"]
update_outstanding = !db.save(doc_with_loc)
So how do I get the Ids?
One option suggested above is that you actively set the id, so you can retrieve it. Ie. if a user sets a given location that is attached to a URL, use the URL. But you may not know which document you want to update - or even have a process that finds all the document that don't have a location and assign one.
You'll most likely be using a view for this. Views have a mapper and a reducer. You'll use the first one, forget about the last one. A view with a mapper does the following:
It returns a simplyfied/transformed way of looking at your data. You can return multiple values per data or skip some. It gives the data you emit a key, and if you use the _include_docs function it will give you the document (with _id and rev alongside).
The simplest view is the default view db.view('_all_docs') this will return all documents and you may not want to update all of them. Views for example will be stored as a document as well when you define these.
The next simple way is to have view that only returns items that are of the type of the document. I tend to have a _type="article in my database. Think of this as marking that a document belongs to a certain table if you had stored them in a relational database.
Finally you can filter elements that have a location so you'd have a view where you can iterate over all those docs that still need a location and identify this in a separate process. The best documentation on writing view can be found here.

Implementing 'delete' method syntax (and set)

I'm writing my first Python class and I was wondering if this was correct syntax to remove a particular 'song' from my dictionary.
I load data from a file onto a dictionary and store it.
Is this syntax correct?
def delete_song(id): #Do I need to do self_song(self, id) instead?
del self.song_names[id]
id is the song's ID, which is being passed. Does this delete a song from my dictionary? Earlier on in the code I had saved a song's name to self.song_names[id]= sname, which was from a component sname=components[1] from reading in the file.
Also, I'm having trouble understanding how to go about the set function. Is this start on the right track?
def set_song(id, list((title,genres))):
self.movie_names[id] = title
self.movie_genres[id] = genres
I figured out how to implement the get method and in it I use
self.song_names[id] = sname and
self.song_genres[id] = sgenre
Any tips?
You should read a chapter on classes here.
And, for deleting an entry from a dictionary, it is safer to use pop:
self.song_names.pop(id, None) <--- will not raise an error if id is not found
del self.song_names[id] <--- raises KeyError if id not found

Categories