2015-03-17 17 views
6

Czy istnieje sposób rekursywnie wywoływania procedur składowanych (a nawet UDF, jeśli to zadziała) na dokumentach DocumentDB?Procedura składowana wywołania DocumentDB z innej procedury składowanej lub samej siebie

Mamy dokument, który wygląda mniej więcej tak:

{ 
    "docID" : "my_id", 
    "owner" : "fred", 
    "items" : [ 
    { 
     "itemID" : "1", 
     "type" : "item", 
     "value" : 3 
    }, 
    { 
     "itemID" : "2", 
     "type" : "group", 
     "items" : [ 
     { 
      "itemID" : "2.1", 
      "type" : "group", 
      "items" : [ 
      { 
       "itemID" : "2.1.1", 
       "type" : "item", 
       "value" : 2 
      }, 
      { 
       "itemID" : "2.1.2", 
       "type" : "item", 
       "value" : 4 
      } 
      ] 
     }, 
     { 
      "itemID" : "2.2", 
      "type" : "item", 
      "value" : 1 
     } 
     ] 
    } 
    ] 
} 

Za każdym razem mamy "items", że "items" tablica może zawierać dane, które są mieszanką "type" : "item" i "type" : "group". Wpisy o numerze "type" : "item" mają proste pole "value", które należy zsumować. Wpisy o numerze "type" : "group" mają tablicę "items" ... i tak dalej. Teoretycznie nie ma ograniczeń co do poziomu rekurencji, co uważam za problem, ale w praktyce poziomy rzadko osiągają poniżej 4 lub 5 głębokości.

Pseudokod dla co próbuję napisać wygląda mniej więcej tak:

function sumValues(items) { 
    int total = 0; 
    forEach(item in items) { 
     if (item.type == "item") { 
      total += item.value; 
     } else { 
      total += sumValues(item.items); 
     } 
    } 
    return total; 
} 

function sumAllValues() { 
    var ctx = getContext(); 
    var coll = ctx.getCollection(); 
    var response = ctx.getResponse(); 

    // query for docs by owner 
    var filterQuery = 'SELECT * FROM Docs d where d.owner = \\\"fred\\\"'; 
    var done = coll.queryDocuments(coll.getSelfLink(), filterQuery, {}, 
    function (err, docs, options) { 
     if (err) throw new Error ('Error' + err.message); 

     var total = 0; 
     docs.forEach(function(doc) { 
     total += sumTotals(doc.items); 
     }); 

     response.setBody('Total: ' + total); 
    }); 
} 

Czy to w ogóle możliwe? Czy funkcja DocumentDB obsługuje wywoływanie sproc z innego sproc? Czy sproc może wywołać sam siebie?

Znalazłem kilka DocumentDB przechowywane referencje procedur on-line, w tym this i this i this i this plus wielu innych stron.

Jeśli jest to możliwe, myślę, że muszę jakoś przetestować kolekcję, aby uzyskać sproc, który chcę wywołać, a następnie jakoś odwołać się do sproc, zamiast po prostu wywoływać sumTotals() bezpośrednio, tak jak w przypadku samodzielnego języka.

Właśnie zaczynamy przyglądać się programowaniu za pomocą DocumentDB, więc nie jesteśmy do końca pewni, co możemy z tym zrobić. Dzięki za pomoc lub radę.

+0

Mogę być w stanie użyć czegoś z [this] (http://www.documentdb.com/javascript/tutorial#transactions) przykład, który definiuje funkcję 'swapItems', która jest wywoływana bezpośrednio z funkcji nadrzędnej. – shoover

+0

Głosuj [tutaj] (https://feedback.azure.com/forums/34192--general-feedback/suggestions/16267270-allow-to-use-udf-user-defined-function-inside-ad), aby dodać ta opcja: –

Odpowiedz

6

Myślę, że jesteś na dobrej drodze.

Niemożliwe jest wykonanie procedury przechowywanej z poziomu procedury składowanej.

Można jednak zdefiniować funkcje JS wewnątrz procedury składowanej, które można przywoływać, wywoływać i ponownie wykorzystywać w ramach tej procedury przechowywanej.

W tym przypadku po prostu zdefiniuj swoją funkcję sumValues() wewnątrz przechowywanej procedury macierzystej sumAllValues() (tak jak wspomniany przykład swapItems()).

function sumAllValues() { 
    var ctx = getContext(); 
    var coll = ctx.getCollection(); 
    var response = ctx.getResponse(); 

    // query for docs by owner 
    var filterQuery = 'SELECT * FROM Docs d where d.owner = \\\"fred\\\"'; 
    var done = coll.queryDocuments(coll.getSelfLink(), filterQuery, {}, 
     function (err, docs, options) { 
      if (err) throw new Error ('Error' + err.message); 

      var total = 0; 
      docs.forEach(function(doc) { 
       total += sumValues(doc.items); 
      }); 

      response.setBody('Total: ' + total); 
     }); 

    function sumValues(items) { 
     int total = 0; 
     items.forEach(function(item) { 
      if (item.type == "item") { 
       total += item.value; 
      } else { 
       total += sumValues(item.items); 
      } 
     }); 
     return total; 
    } 
} 

Można także zdefiniować funkcje UDF dla logiki, którą chcesz udostępnić i ponownie użyć w wielu przechowywanych procedurach i zapytaniach.

+1

Ta sugestia - przenoszenie definicji funkcji sumValues ​​do definicji sproc - działała dla mnie, więc zaktualizowałem twoją odpowiedź za pomocą przykładu kodu i ją zaakceptuję. – shoover