dgreceanu of The Code Killers
1/29/2014 - 8:45 PM

De la versiunea 1.4 în sus, CouchDB permite cuplarea unei funcții LIST și cu view-ul _all_docs care dă pe țeavă toate înregistrările din baz

De la versiunea 1.4 în sus, CouchDB permite cuplarea unei funcții LIST și cu view-ul _all_docs care dă pe țeavă toate înregistrările din bază! Asta este un lucru bun pentru că cuplarea unei funcții LIST cu un view scris de utilizator înseamnă parcurgerea a doi arbori: prima dată a B-tree-ului view-ului (indexului) și a doua oară, pe sărite , în B-tree-ul înregistrărilor clusterizate pe _id (că înregistrările din bază pot fi altfel aruncate in arbore în alte locuri) fapt care echivalează cu un full-lookup permanent [tree view] - [tree bază] !!! La multe înregistrări, asta poate dura mult ! Dacă înregistrările ce trebuie întoarse trebuie MUSAI să fie sortate după un anumit câmp (și nu se poate face sortarea pe browser la client) atunci singura soluție posibilă este definirea unui view, în modul clasic! Dar dacă vreau să fac rapid obținerea tuturor înregistrărilor într-un format mai scurt, cu selecția doar a anumitor câmpuri, se poate și cum arăt în continuare mai jos!

I-a venit cuiva în minte să cupleze o funcție LIST direct la ieșirea pipe-ului de la _all_docs, asta înseamnă parcurgerea în chunk-uri mari a B-tree-ului de bază și apelarea ca un filtru a funcției LIST fără du-te-vino a capului pe disc între index și bază! Totul bine și frumos DAR ... plm , în _all_docs mai vin de-a valma și alte documente, cum ar fi de exemplu _design/docs !!!

Pentru a putea face corect filtrarea acestora, am dat mai jos exemplul unei funcții LIST scrise în Erlang ce ia toate înregistrările din bază, evită înregistrările care nu au câmpul <<"Siruta">> definit în Doc și asamblează Row-urile într-un Array corect JSON cu înregistrările localităților (în exemplul de mai jos) ! Implementarea de mai jos echivalează cu un soi de SELECT * FROM _all_docs WHERE Siruta IS NOT NULL AND (... se mai pot pune și alte condiții ) !

fun(Head, {Req}) ->
    Send(<<"[">>),
    Fun = fun({Row}, Virgula) ->
        Send(Virgula),
        case proplists:get_value(<<"doc">>, Row) of
        {Doc} ->
            %% mă asigur că nu trimit altceva decât documente de tip "localitate"
            %% și nu am primit din view și vreun document de tip _design
            Elocalitate = proplists:is_defined(<<"Siruta">>, Doc),
            if
                Elocalitate ->
                    Campuri = [ 
                        proplists:get_value(<<"_id">>, Doc),
                        proplists:get_value(<<"Nume">>, Doc),
                        proplists:get_value(<<"Siruta">>, Doc),
                        proplists:get_value(<<"Județ">>, Doc)
                    ],
                    Send(iolist_to_binary(mochijson2:encode(Campuri))),
                    {ok, <<",">>};
                true ->
                    {ok,Virgula}
            end;
        _ ->
            {ok, <<",">>}
        end
    end,
    {ok, _} = FoldRows(Fun, <<"">>),
    <<"]">>
end.