pymongo update_one not updating based on _id - python

I have this change set:
change_set = {'name': 'bso save job again', 'location': 'new york city', 'expires': '2020-04-04', 'created': '2020-03-05'}
with this id (i'm not creating this id, it is actually from an earlier save):
id = '5e6107ddfef5aa3c2e3647b2'
I'm trying to do this:
result = dbjobs.update_one({'_id': id}, {'$set': change_set})
my result.raw_result is this:
{'n': 0, 'nModified': 0, 'ok': 1.0, 'updatedExisting': False}
Its not throwing an error, I'm just getting zero change. Am I updating wrong?

TLDR: your id should be of type ObjectId and not string.
Add this to your code:
from bson.objectid import ObjectId
id = ObjectId('5e6107ddfef5aa3c2e3647b2')
Short explanation for debugging such issues:
From looking at the return value of update_one specifically the ok field returns 1, meaning the operation succeeded.
Combine that with the fact that n=0 meaning that Mongo is not able to match any documents, hence the problem is in the query section of the operation.

Related

How do i get the document id in Marqo?

i added a document to marqo add_documents() but i didn't pass an id and now i am trying to get the document but i don't know what the document_id is?
Here is what my code look like:
mq = marqo.Client(url='http://localhost:8882')
mq.index("my-first-index").add_documents([
{
"Title": title,
"Description": document_body
}]
)
i tried to check whether the document got added or not but ;
no_of_docs = mq.index("my-first-index").get_stats()
print(no_of_docs)
i got;
{'numberOfDocuments': 1}
meaning it was added.
if you don't add the "_id" as part of key/value then by default marqo will generate a random id for you, to access it you can search the document using the document's Title,
doc = mq.index("my-first-index").search(title_of_your_document, searchable_attributes=['Title'])
you should get a dictionary as the result something like this;
{'hits': [{'Description': your_description,
'Title': title_of_your_document,
'_highlights': relevant part of the doc,
'_id': 'ac14f87e-50b8-43e7-91de-ee72e1469bd3',
'_score': 1.0}],
'limit': 10,
'processingTimeMs': 122,
'query': 'The Premier League'}
the part that says _id is the id of your document.

How to return a specific fields using Pymongo and MongoDB?

I am trying to return just two fields from my MongoDB database and this query correct sends back my username and posts from the client:
db.users.find({'email_address': /^johnny/}, {'username': 1, 'user_posts': 1, '_id': 0});
I'm trying to switch this to PyMongo so I can query in Python and my query looks like this:
regx = Regex('^{0}'.format('johnny'))
query = {'postcode': regx}, {'username': 1, 'user_posts': 1, '_id': 0}
user_list = mycol.find(query).limit(5)
The bit where it's failing is here:
{'username': 1, 'user_posts': 1, '_id': 0}
As without this filter the documents are sent in full fine. With that I get this error message from PyMongo:
TypeError: filter must be an instance of dict, bson.son.SON, or any other type that inherits from collections.Mapping
I assume that my filter is malformed and it's no longer a dictionary so have tried various alternatives of wrapping in quotes and then .format() etc but cannot seem to hit the magical combination.
The problem is that the following is not a dictionary but a tuple of two dictionaries:
query = {'postcode': regx}, {'username': 1, 'user_posts': 1, '_id': 0}
if you wanted to use it directly you could do it with
user_list = mycol.find(query[0], query[1]).limit(5)
but probably best to actually assign it to two separate variables like so
query, filter = {'postcode': regx}, {'username': 1, 'user_posts': 1, '_id': 0}
and then
user_list = mycol.find(query, filter).limit(5)
Turned out it was quite easy.. I just needed to have two dictionaries. 1 for the query and the other for the filter.
regx = Regex('^{0}'.format('johnny'))
filter_stuff = {'username': 1, 'user_posts': 1, '_id': 0}
Then just build the full query as follows:
user_list = mycol.find(query, filter_stuff).limit(5)

How to return field of record after update query with upsert as true in mongodb using pymongo?

I am trying to to insert record in mongodb but I dont want duplication so I am using update command with upsert=true
import pymongo
client = pymongo.MongoClient(settings.MONGO_DB_URI)
db = self.client[settings.MONGO_DB_NAME]
filter = {
'my_id': '1234',
'name': 'alok'
}
record = {
'my_id': '1234',
'name': 'alok',
'marks': 26
}
status = db['mycollection'].update(filter, {'$setOnInsert': record}, upsert=True)
print('id is ', status['my_id']) # this will not work but I want such behaviour
This code will insert record only if there is no existing record with matching filter values. So there are two case:
It will insert record
It will not insert record if already exist
In both the case I want to get my_id. How can I get my_id when update command execute?
You can search for the document and then print out its ID
print('id is ', db['mycollection'].find_one(filter)['my_id'])

How to use my original key for identifying a doc in Cloudant db from Python client?

I'm working on a python client program to Cloundant.
I'd like to retrieve a doc, not based on "_id",but on my own field.
Still, it does not work causing Key Error. Any help to solve this error is highly appreciated!
Here is my code:
from cloudant.client import Cloudant
from cloudant.error import CloudantException
from cloudant.result import Result,ResultByKey
...
client.connect()
databaseName = "mydata1"
myDatabase = client[databaseName]
# As direct access like 'doc = myDatabase[<_id>]' cannot work for my key,
# let's check on by one ...
for document in myDatabase:
# if document['_id']== "20170928chibikasmall": <= if I use _id it's ok
if document['gokigenField']== 111:
This cause
KeyError :'gokigenField'
In advance, I've created gokigenField index using dashboard, then confirm the result via my postman with REST API
GET https://....bluemix.cloudant.com/mydata1/_index
the result is as follows:
{"total_rows":2,"indexes":[{"ddoc":null,"name":"_all_docs","type":"special","def":{"fields":[{"_id":"asc"}]}},{"ddoc":"_design/f7fb53912eb005771b736422f41c24cd26c7f06a","name":"gokigen-index","type":"text","def":{"default_analyzer":"keyword","default_field":{},"selector":{},"fields":[{"gokigenField":"number"}],"index_array_lengths":true}}]}
Also, I've confirmed I can use this gokigenField as query index nicely on cloudant dashboard as well as POST query .
My newly created "gokigenField" is not included in all the document in DB, as there are automatically created doc ("_design/xxx) without that field.
I guess this might cause KeyError, when I call this from my Python client.
I cannot find Cloudant API for checking 'if a specific key exists or not in a document', in the reference.. So, cannot have any idea how to by-pass such docs...
This is how to index an query data from the Python client. Let's assume we already have the library imported and have a database client in myDatabase.
First of all I created some data:
#create some data
data = { 'name': 'Julia', 'age': 30, 'pets': ['cat', 'dog', 'frog'], 'gokigenField': 'a' }
myDatabase.create_document(data)
data = { 'name': 'Fred', 'age': 30, 'pets': ['dog'], 'gokigenField': 'b' }
myDatabase.create_document(data)
data = { 'name': 'Laura', 'age': 31, 'pets': ['cat'], 'gokigenField': 'c' }
myDatabase.create_document(data)
data = { 'name': 'Emma', 'age': 32, 'pets': ['cat', 'parrot', 'hamster'], 'gokigenField': 'c' }
myDatabase.create_document(data)
We can check the data is there in the Cloudant dashboard or by doing:
# check the data is there
for document in myDatabase:
print(document)
Next we can opt to index the field gokigenField like so:
# create an index on the field 'gokigenField'
mydb.create_query_index(fields=['gokigenField'])
Then we can query the database:
# do a query
selector = {'gokigenField': {'$eq': 'c'}}
docs = mydb.get_query_result(selector)
for doc in docs:
print (doc)
which outputs the two matching documents.
The python-cloudant documentation is here.

How to convert neomodel object into json? (is not JSON serializable)

I use Falcon framework and neomodel in order to communicate with neo4j database.
I have some nodes in DB and I try to return information about them via API (get methon) as a JSON object.
In order to retrive information I use the code people = Person.nodes
I iterate throu people:
for p in people:
print(p)
and I get:
{'name': 'John', 'id': 0, 'uid': '584d9b0517584b8194f222052bf177ff'}
{'name': 'Paul', 'id': 1, 'uid': 'f5763c01704e449885f846e87e1fcb6d'}
When I do json.dumps() on single entity I get an error:
TypeError: <Person: {'name': 'John', 'id': 0, 'uid': '584d9b0517584b8194f222052bf177ff'}> is not JSON serializable
How can I convert neomodel object into json object?
Using json.dumps(p.__properties__) does the trick. Using p.__dict__ tries to encode the neomodel property classes, which will throw an error.
It seems like every p in your people is an object.
Try something like json.dumps(p.__dict__). If it's a common neomodel node object then this should work.
A bit of an old question but this is how I work with this..
Creating a function on the class so I can control what data to return. With __properies__ instead of the .to_json funtion you will get all properties.
class Player(StructuredNode):
mid = IntegerProperty(unique_index=True)
f_name = StringProperty()
l_name = StringProperty()
email = StringProperty()
team = RelationshipFrom('Team', 'PLAYER', model=PlayerRel)
def to_json(self):
return {
"id": self.mid,
"firstName": self.f_name,
"lastName": self.l_name,
"email": self.email,
"fullName": self.f_name + ' ' + self.l_name
}
Then I have a node with has several Players connected and I just do this to return an array of players that can be serialized:
...
team = Team.nodes.get(team_id=id)
return ([player.to_json() for player in team.players])

Categories

Resources