histrio/py-couchdb

Add a method for fetching just one value from the database?

flexd opened this issue · 9 comments

I have a query like this

balance = int(list(db.query('balance/all', descending='true', limit='1'))[0]['value'])

Which as you can see is a lot less cleaner then being able to do something like this

balance = int(db.one('balance/all'))

Or something similiar, I don't know. I just found it a bit annoying to have to do [0] and especially ['value'] to get the value of a specific document like that.

Suggestions?

Hi!

The second option seems very cleaner, but the library can't guess the attribute name.

int(db.one("balance/all")["value"])

or

int(db.query("balance/all", flat="value", limit=1))

also, the one method can be a first method.

I don't known that is the cleaner or semantically correct method.

{
"total_rows": 480,
"offset": 0,
"rows": [
{
"id": "07678d458cee44cebf307230beb39170",
"key": "1368053775",
"value": 6437992388.73
},
{
"id": "599d54d35b5c4615a30b133fc1aaf063",
"key": "1368055731",
"value": 6183660317.03
}
]
}

The result is always in that format from the database isn't it, at least if you have something that doesn't return a whole doc, like this python view:

def fun(doc):
  if (doc['.type'] == 'Balance'):
    yield doc['timestamp'], doc['balance']

Oh, you abosultelly right.

With this, we can improve query method and add a one method:

  • Change query method behavior: by default returns a tuple (key, value) and if you only need a value or a key yo can use a flat parameter.
[("foo", 1), ("bar", 2)] == db.query("foobar/all")
[1,2] == db.query("foobar/all", flat="value")
["foo", "bar"] == db.query("foobar/all", flat="key")
  • Add one method.
("foo", 1) == db.one("foobar/all")
1 == db.one("foobar/all", flat="value")
"foo" == db.one("foobar/all", flat="key")

What do you think about this?

That looks nice, but how would that look for a normal document?, say:

{
   "_id": "2856703783",
   "_rev": "1-d169903d3091e1f0d5f896458d6722ab",
   "timestamp": 1367443028,
   "price": 1068903.96,
   ".type": "Transaction",
   "station": {
       "id": 60008494,
       "name": "Amarr VIII (Oris) - Emperor Family Academy"
   },
   "id": 2856703783,
   "for": "personal",
   "journal_id": 7422767310,
   "client": {
       "id": 1292578043,
       "name": "Aedazan"
   },
   "action": "sell",
   "type": {
       "id": 3888,
       "name": "Co-Processor II"
   },
   "quantity": 1
}

By the way, it was also annoying me a bit (and caused some errors at first) that I had to do parameters like this:

transactions = list(db.query('transactions/all', descending='true', limit='25'))

Instead of using 'native' values for python like this:

transactions = list(db.query('transactions/all', descending=True, limit=25))

But that isn't that much of an issue, it's just a matter of nice syntax.

The view queryes always return kay and value. If you need a entire document, write a query like a:

def fun(doc):
  if (doc['type'] == 'Balance'):
    yield doc['timestamp'], doc

This returns:

{
    "total_rows": 480,
    "offset": 0,
    "rows": [
        {
            "id": "07678d458cee44cebf307230beb39170",
            "key": "1368053775",
            "value": {"_id": "2856703783", "_rev": "1-d169...", "price": 2.2, ...}
        },
       [...]
    ]
}

And obtain this value with this:

{"_id": "2856703783", "_rev": "1-d169...", "price": 2.2, ...} == db.one("foobar/all", flat="value")

Right, I guess you might want to make the flat="value" default in the code as well, so you can do just db.one("foobar/all") and db.all("foobar/all") to get just a list of values and no keys? Like it is now.

I like it!

I think that the flat parameter as a None for default, because I don't like break current api.
But with this implemented, you have a cleaner api for obtain a values list.

I make this changes tomorrow ;)

Thanks for the idea!

Cool! :-)

Now implemented :)