Поиск нескольких ключей в CouchDB

учитывая следующую структуру объекта:

{
   key1: "...",
   key2: "...",
   data: "..."
}

есть ли способ получить этот объект из CouchDB, задавая как key1, так и key2 без настройки двух разных представлений (по одному для каждого ключа), например:

select * from ... where key1=123 or key2=123

С уважением, Artjom

edit:

вот лучшее описание проблемы: Объект, описанный выше, является сериализованным состоянием игры. В игре есть ровно один пользователь-создатель (key1) и его противник (key2). Для данный пользователь я хотел бы получить все игры, в которых он участвует (как создатель, так и противник).

4 ответов


Испустите оба ключа (или только один, если они равны):

function(doc) {
  if (doc.hasOwnProperty('key1')) {
    emit(doc.key1, 1);
  }
  if (doc.hasOwnProperty('key2') && doc.key1 !== doc.key2) {
    emit(doc.key2, 1);
  }
}

запрос (правильно url-кодируется):

?include_docs=true&key=123

или с несколькими значениями:

?include_docs=true&keys=[123,567,...]

обновление: обновлено для запроса нескольких значений с помощью одного запроса.


вы можете создать представление CouchDB, которое производит такие выходные данные, как:

["key1", 111],
["key1", 123],
["key2", 111],
["key2", 123],
etc.

очень просто написать представление карты в javascript:

function(doc) {
    emit(["key1", doc["key1"]], null);
    emit(["key2", doc["key2"]], null);
}

при запросе вы можете запросить с помощью нескольких ключей:

{"keys": [["key1", 123], ["key2", 123]]}

вы можете отправить этот JSON в качестве данных в сообщении в представление. Или предпочтительно использовать API для вашего языка программирования. Результатом этого запроса будет каждая строка в представлении, которая соответствует любому ключу. Итак, каждый документ, который соответствует обоим key1 и KEY2 вернет две строки в результатах просмотра.


Я также боролся с simular вопросом, как использовать

"select * from ... where key1=123 or key2=123". 

следующее представление позволит вам искать документы клиента по фамилии или поля FirstName:

function(doc) {
  if (doc.Type == "customer") {
      emit(doc.LastName, {FirstName: doc.FirstName, Address: doc.Address});
      emit(doc.FirstName, {LastName: doc.LastName, Address: doc.Address});
  }
}

Я нашел здесь приведенный выше ответ:https://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Map_Functions


Я использую это для веб-службы, которая запрашивает все мои документы и возвращает каждый документ, соответствующий существованию узла и запроса. В этом примере я использую узел "detail" для поиска. Если вы хотите выполнить поиск в другом узле, вам нужно указать.

Это мой первый пост переполнения стека, поэтому я надеюсь, что смогу помочь кому-то:)

***Python Code

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import httplib, json

from tornado.options import define,options

define("port", default=8000, help="run on the given port", type=int)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        db_host = 'YOUR_COUCHDB_SERVER'
        db_port = 5984
        db_name = 'YOUR_COUCHDB_DATABASE'

        node = self.get_argument('node',None)
        query = self.get_argument('query',None)

        cleared = None
        cleared = 1 if node else self.write('You have not supplied an object node.<br>')
        cleared = 2 if query else self.write('You have not supplied a query string.<br>')

        if cleared is 2:
            uri = ''.join(['/', db_name, '/', '_design/keysearch/_view/' + node + '/?startkey="' + query + '"&endkey="' + query + '\u9999"'])
            connection = httplib.HTTPConnection(db_host, db_port)
            headers = {"Accept": "application/json"}
            connection.request("GET", uri, None, headers)
            response = connection.getresponse()
            self.write(json.dumps(json.loads(response.read()), sort_keys=True, indent=4))

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", MainHandler)
        ]
        settings = dict(
            debug = True
        )
        tornado.web.Application.__init__(self, handlers, **settings)

def main():
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == '__main__':
    main()


***CouchDB Design View
{
   "_id": "_design/keysearch",
   "language": "javascript",
   "views": {
       "detail": {
           "map": "function(doc) { var docs = doc['detail'].match(/[A-Za-z0-9]+/g); if(docs) { for(var each in docs) { emit(docs[each],doc); } } }"
       }
   }
}