2012-05-30 2 views
6

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

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

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

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

С наилучшими пожеланиями, Artjom

редактировать:

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

ответ

4

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

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,...] 

ОБНОВЛЕНИЕ: обновлено до запрашивать несколько значений с помощью одного запроса.

2

Вы можете создать вид 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 в качестве данных в POST к представлению. Или желательно использовать API для вашего языка программирования. Результатом этого запроса будет каждая строка в представлении, соответствующая любому ключу. Таким образом, каждый документ, который соответствует как key1, так и key2, будет возвращать две строки в результатах просмотра.

0

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

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

***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); } } }" 
     } 
    } 
} 
+0

Запрос URI выглядит следующим образом: HTTP: // локальный: 8000/узел = подробно & запроса = робот – publicmat

+0

Добро пожаловать на SO. Вы всегда можете отредактировать свой собственный пост, чтобы добавить соответствующую информацию, нажав на ссылку «изменить» под ним. Вы должны сделать это и удалить свой комментарий, как только информация будет в вашем ответе :) Удачи, посмотрите в нашу секцию справки для получения дополнительной информации: http://stackoverflow.com/review/late-answers/3596626# – ForceMagic

1

Я также борется с Двойники вопрос, как использовать

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

следующий вид позволит вам искать документы клиента по LastName или. Сначала введите следующие поля:

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

Смежные вопросы