2

I have a DB in CouchDB and I'm wondering if is it possible to create a view directly from python instead of using GUI. I'm a beginner in CouchDB and I need a function that's equivalent at SELECT DISTINCT in SQL and a view like

function (doc) {
  if(doc.MovieId == "1254")
    emit(doc.Rating, 1);
}

is the ideal. The problem is that I've to do this view for much more MovieIds (taken from keyboard input).

I'm asking you if is possible to create/delete views like this directly from python because on the net I've found nothing. If isn't possible, is that a good idea to make a Mango query and map results by myself?

---EDIT---

json_data = {
  "_id": "_design/titaRat",
  "_rev": "3-ceb11154b13457c55b1f98f4e9d15b03",
  "views": {
    "titRat": {
      "map": "function (doc) { var id_prefix = \"ratings :\"; if(doc._id.substr(0, id_prefix.length) === id_prefix && doc.MovieId == \"1721\") emit(doc.Rating, 1);}",
      "reduce": "_count"
    }
  },
  "language": "javascript",
  "options": {
    "partitioned": False
  }
}

db.save(json_data)


ResourceConflict: ('conflict', 'Document update conflict.')

I got this error, but there aren't document that have this name

  • 1
    does the document with the id ```"_design/titaRat"``` already exist? A document update conflict comes when you don't provide the correct ```_rev``` for an existing document of if you include a ```_rev``` in a new document. If this is a new document please remove the ```_rev``` – Joshua Beckers May 01 '20 at 14:00
  • the document doesn't exists, but I wanted to cheat by copying the JSON document from the GUI and I had forgotten to remove the "_rev" field ... I'm feeling so stupid hahaha It works now, thank you –  May 01 '20 at 14:43

2 Answers2

1

I have a function for this:

def createView( dbConn, designDoc, viewName, mapFunction ):
    data = {
            "_id": f"_design/{designDoc}",
            "views": {
                viewName: {
                    "map": mapFunction
                    }
            },
            "language": "javascript",
            "options": {"partitioned": False }
            }
    logging.info( f"creating view {designDoc}/{viewName}" )
    dbConn.save( data )

An example of the call would be:

mapFunction = '''function (doc) {
                      if( doc.type == 'word')
                      emit(doc.word, doc);
                    }'''
createView( db, "DESIGN_DOC_NAME", "VIEW_NAME", mapFunction )
Raul Luna
  • 1,945
  • 1
  • 17
  • 26
0

You can create a view from python the same way you would create any document in couch deb.

The difference is that you would need to create a design document.

The document for your function would look like this:

{
  "views": {
    "movie_ratings_view": {
      "map": "function(doc) { if(doc.MovieId == "1254") emit(doc.Rating, 1); }",
    }
  }
}

As you see the map function is saved as a string. If you want to add formating you would need to add it with \n and \t for example.

To save this document you would POST it to POST /{db}/_design/movie_ratings_ddoc

You can then call your view via GET /{db}/_design/movie_rations_ddoc/_view/movie_ratings_view

You can save multiple views per design document.

If you want to delete a view you can either delete the entire design document or just update the design doc with the view removed from the object.

For further information on how to use views read: https://docs.couchdb.org/en/master/api/ddoc/views.html

Joshua Beckers
  • 857
  • 1
  • 11
  • 24
  • I've tried that and I've tried also to save the ddoc that I've create from GUI, but when I do db.save(document) I have "document _id must be partion:_id" error. I've no idea about how to do –  May 01 '20 at 07:43
  • 1
    @Malotino You need to either put "options": { "partitioned": false } into the document if you want the vie to be global, or form the _id in the format "{partition_id}:{document_id}" if the view is for the local partition. Let me know if it works. – Joshua Beckers May 01 '20 at 10:51
  • I was unable to do that in python, it gave me a lot of errors in the JSON document. I've done it in a few minutes with a query that works with MovieId taken from keybord and then I've mapped the results by me ... maybe it's not the best solution but it works –  May 01 '20 at 11:10
  • 1
    @Malotino can you update your question? Please post what you tried and post the error message. Then I can look into it. – Joshua Beckers May 01 '20 at 11:12