Add a validator to a Mongodb collection with pymongo - python

I am trying to add a validator to a MongoDB collection using pymongo.
The command I would like to run adapted from here
Is equivalent to this:
db.runCommand( {
collMod: "contacts",
validator: { phone: { $type: 'string' } },
validationLevel: "moderate"
} )
{ "ok" : 1 }
And subsequently will throw an error if a non-string datatype is inserted tin the phone field
Using python I did the following:
db.command({'collMod': 'contacts',
'validator': {'phone': {'$type': 'string'}},
'validationLevel': 'moderate'})
.
.
.
InvalidDocument: Cannot encode object: Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test_table'), 'contacts')
I'm sure that my python interpretation is wrong, that much is clear, however I have not been able to find the correct translation, or whether this is even possible in python

I eventually found the solution here. Hopefully it can help someone else.
Of course, when all else fails read the docs...
.. note:: the order of keys in the command document is
significant (the "verb" must come first), so commands
which require multiple keys (e.g. findandmodify)
should use an instance of :class:~bson.son.SON or
a string and kwargs instead of a Python dict
Also valid is an OrderedDict
query = [('collMod', 'contacts'),
('validator', {'phone': {'$type': 'string'}}),
('validationLevel', 'moderate')]
query = OrderedDict(query)
db.command(query)
{'ok': 1.0}
EDIT:
Current Documentation from where the above comes from. Note this was added after the question was originally answered so the documentation has changed, however it should still be relevant

Related

How to see what can be set/updated on an issue?

I'm trying to use the JIRA Python API to create and update issues on different projects.
Currently I'm after timetracking but I've seen other fields that cannot be set on this or that project getting the error message:
... cannot be set. It is not on the appropriate screen, or unknown.
I can already set timetracking on some projects like:
issue.update(fields={'timetracking': {'originalEstimate': '4h'}})
But on others I get the mentioned error message although the field is clearly present among the issue fields:
>>> issue.fields.timetracking
<JIRA TimeTracking at 2072336111640>
There seems to be nothing obvious on the object itself that could make me identify the thing as "not set-able".
Here is a post on how to get the fields on the screen via REST API. I think that's what the Python thing is doing in the background. But do I really need to go that way?
Given the path from the REST API question answer we can get the data with the private _get_json:
path = 'issue/createmeta?projectKeys={KEY}&expand=projects.issuetypes.fields'
data = jira_connection._get_json(_FIELDS_PATH.format(KEY=project_key))
project_fields = {}
for issuetype in data['projects'][0]['issuetypes']:
project_fields[issuetype['name']] = dict((f, v['name']) for f,v in issuetype['fields'].items())
This will result in a project_fields dictionary like:
{
"ISSUE_TYPE_NAME": {
"FIELD_ID": "FIELD_NAME",
...
}, // for example:
"Task": {
"summary": "Summary",
"issuetype": "Issue Type",
...
}
}
As long as there is no such feature in the jira package directly.

Converting Python Dict to JSON for MySQL field of JSON type

I am currently getting this error:
Invalid JSON text: "not a JSON text, may need CAST" at position 0 in value for column
This is the value that is trying to be inserted:
{
"ath": 69045,
"ath_date": "2021-11-10T14:24:11.849Z",
"atl": 67.81,
"atl_date": "2013-07-06T00:00:00.000Z"
}
When trying to insert into my database. I believe it is due to malformed JSON however I am using json.dumps() to convert my dictionary. I have tried several things I have found over the last few hours to try and format it correctly but am hitting a wall between two errors.
I tried adding another level as well as wrapping it all in an array as that was recommended in another question, however, that produced the same error.
My Dict:
ticker_market_data[ticker] = {
"all_time": {
"ath": market_data["ath"]["usd"],
"ath_date": market_data["ath_date"]["usd"],
"atl": market_data["atl"]["usd"],
"atl_date": market_data["atl_date"]["usd"],
},
"price_change_percent": {
"1h": market_data["price_change_percentage_1h_in_currency"]["usd"],
"24h": market_data["price_change_percentage_24h"],
"7d": market_data["price_change_percentage_7d"],
"30d": market_data["price_change_percentage_30d"],
"1y": market_data["price_change_percentage_1y"],
},
}
The problem items being all_time and price_change_percent.
This is how I am creating the variables to store in the database:
all_time = json.dumps(ticker_market_data[ticker].get("all_time"))
price_change_percent = json.dumps(ticker_market_data[ticker].get("price_change_percent"))
I wanted to answer my own question though I don't know how much it will benefit the community as it was completely on me. My code posted above was entirely correct, the problem lay in the order of variables being inserted in the SQL. I had the wrong type of variable one position up from where it needed to be. So rather than JSON being inserted into the column it was a float.

Any suggestions to customize an analyzer when using query match with elasticsearch-py?

I can't apply a custom analyzer when using query match with elasticsearch-py.
I customized an analyzer called custom_lowercase_stemmed and used es.indices.put_settings to update the index setting.
However, it couldn't find the analyzer when I do a search.
I also looked into the parameter analyzer in es.search, but it returns an error:
..unrecognized parameter: [analyzer]
Can I get any suggestions here in terms of a customized analyzer? Thank you!
query_body = {
"query": {
"match": {
"employer":{
"query": txt,
"fuzziness": 'AUTO',
"analyzer" : 'custom_lowercase_stemmed'
}
}
}
}
es.search(index='hello',body=query_body)
Here is the full error:
RequestError: RequestError(400, 'search_phase_execution_exception', '[match] analyzer [custom_lowercase_stemmed] not found')
I think you have to make sure you have the following:
Have your Configuration set properly. In your case, you should have in your settings the field "custom_lowercase_stemmed" as analyzer. You can also define the words you want to stop.
With the Python ES Client, you have to send the analyzer as a parameter of the method .search(). Check the docs. However, you can try to run your query as it is. I haven't played that much with analyzer.
Hope this is helpful! :D
Ensure that you have specified your analyzer at your mapping and ensure your querying the correct field as well.
For your question on the matching problem for removing duplicate names, at term level and short words, fuzziness and wildcard parameters would be the best fit!
Cheers,
Min Han (:

OR condition in motor python

Hi I am experimenting with python and mongodb with tornado framework. I am having entry module where user can insert the data of students in academic and sports field. In mongodb terminal I did search with
db.student.find( { $or: [ { "academy": name }, { "sports": name } ] } )
but when I try to do the same with python along with MOTOR driver I end up with error.
My python command is
doc = yield db.student.find_one({ $or: [{"academy": name}, {"sports": name}]})
Can anyone guide me how I can do the search with or condition in python motor?
The or condition is used to check whether the data of particular student is entered in both the fields or not.
You write, "I end up with an error", but it is very difficult for anyone to answer your question if you don't tell us what the error is!
In this particular case I think I know the problem. In Python, all field names must be quoted. The proper syntax is:
doc = yield db.student.find_one({ "$or": [{"academy": name}, {"sports": name}]})

Python Eve - where clause using objectid

I have the following resource defined in settings.py,
builds = {
'item_title': 'builds',
'schema': {
'sources': {
'type': 'list',
'schema': {
'type': 'objectid',
'data_relation': {
'resource': 'sources',
'embeddable': True,
}
}
},
'checkin_id': {
'type': 'string',
'required': True,
'minlength': 1,
},
}
}
When I try to filter based on a member whose value is an objectid, I get empty list.
http://127.0.0.1:5000/builds?where={"sources":"54e328ec537d3d20bbdf2ed5"}
54e328ec537d3d20bbdf2ed5 is the id of source
Is there anyway to do this?
Your query should work just fine assuming that you actually have the 54e328ec537d3d20bbdf2ed5 value included in any sources field within any builds document.
What I mean is, you can't query the builds endpoint for the existence of a document in the sources endpoint (you can of course do that at the sources endpoint.) But, if you actually store a builds document and it references a sources document, then you query will work fine because what you are actually asking is "get me all builds documents which have a reference to this sources document". For example, if you POST a document like this to the builds endpoint:
{
"sources": ["54e328ec537d3d20bbdf2ed5"]
"checkin_id": "A"
}
Then this query:
http://127.0.0.1:5000/builds?where={"sources":"54e328ec537d3d20bbdf2ed5"}
Will return that one document. Of course since you defined sources as embeddable you can also do:
http://127.0.0.1:5000/builds?where={"sources":"54e328ec537d3d20bbdf2ed5"}&embedded={"sources":1}
Which will get you referenced documents embedded along with any matching document, like so:
{
"sources": [{"field1": "hey", "field2":"I'm an embedded source"}]
"checkin_id": "A"
}
Whereas you would get a 'raw' document without the explicit embed. It is probably worth mentioning that you can also enable predefined embedding of referenced resources, so your clients don't have to explicitly request an embed.
Hope this helps.
New to Eve but I have an advance on Nicola's "should work", because my experience is that it does not and as this question is what comes up when looking trying to deal with the frustration of figuring out why...
Debugging this the library got me to the point where Eve automagically decides that something with a signature that looks like "54e328ec537d3d20bbdf2ed5" should be cast to an ObjectId, which is all good. However, then the comparison of type ObjectId:54e328ec537d3d20bbdf2ed5 against type string:54e328ec537d3d20bbdf2ed5 is not an equality so your filter returns no results
The really simple solution is to change checkin_id to ObjectId. Eve starters can be assured you don't need all the additional decorations, so in the above example just change 'type':'string' to 'type':'objectId' and will be good. Specifically, if you have calling code where this field is defined as a string, you can leave it as it is, the cast will occur within eve as described above and it will just work as expected.
edit - See also eve's schema level "query_objectid_as_string" configuration setting for which upon reading seems to override this behaviour.

Categories