2016-08-06 13 views
6

w moim obecnym Mongo DB, mam proste Części kolekcję, ze stosunków między rodzicami dzieci, jak następuje:Mongoose: Znajdź etykietę w tablicy i zwraca dopasowanie dokumentów

{"partcode": "Parent1","children": ["Child1","Child2","Child3"]} 

{"partcode": "Child1","label": ["label1"]} 
{"partcode": "Child2","label": ["label1"]} 
{"partcode": "Child3","label": ["label1"]} 

W celu powrotu dzieci partcode, korzystać z następujących funkcji: Mongoose

PartSchema.static('getChildren', function(query, callback) { 
    var self = this, 
    self.findOne(query, {children: 1, _id: 0}) 
    .exec(function(err, doc) { 
     return (self.find({ 
     "partcode": { 
      "$in": doc.children 
     } 
     }, {_id: 0}, callback)); 
    }); 
}); 

ta zwraca następującą macierz:

[{"partcode": "Child1","label": ["label1"]}, 
{"partcode": "Child2","label": ["label1"]}, 
{"partcode": "Child3","label": ["label1"]}] 

Chciałbym zaimplementować system etykiet, w którym mogę określić etykietę jako meta-dziecko, i kod, aby zwrócić wszystkie dzieci pasujące do tej etykiety.

{"partcode": "Parent1","children": ["*label1"]} 

wróci:

[{"partcode": "Child1","label": ["label1"]}, 
{"partcode": "Child2","label": ["label1"]}, 
{"partcode": "Child3","label": ["label1"]}] 

będę określić etykietę u dzieci w dziedzinie dokumentu nadrzędnego jako zaczynające się od znaku specjalnego (obecnie używam „*”, ale szczęśliwy, aby zmienić do czegoś innego, jeśli zajdzie taka potrzeba).

Pseudokod:

  1. znaleźć nadrzędna
  2. Get rodzic „s dzieciom tablicę
  3. W tablicy, jeśli dziecko rozpoczyna się etykiecie znaków
    1. dostać tablicę wszystkich partcodes z części pasujących etykiety i
    2. partcodes zastępczych na etykiecie dzieci tablicy
  4. obie dzieci tablica

dzieci, które nie są poprzedzone znak etykiety również powinien zostać zwrócony.

+1

możesz używać wyrażeń regularnych w instrukcji $ in. Coś w rodzaju 'find ({label: {$ in: [/ label1 /]}}, callback)' Pamiętaj, aby dodać indeks dla pola 'label' – Andreas

+0

Dzięki za to. Nie mam nic przeciwko szczegółowi wokół znaleziska. Stworzyłem funkcję etykiety, która zwraca wszystkie obiekty z określoną etykietą. Nie jestem pewien, jak najlepiej to zorganizować; to znaczy szerokie pociągnięcia. Przechodzę w kierunku rurociągu Aggregate. – Terry

Odpowiedz

1

Dostałem to do pracy w następujący sposób:

PartSchema.static('getChildren', function(query, callback) { 
    var self = this, 
    children = [], 
    labels = []; 
    self.findOne(query, {children: 1, _id: 0}) 
    .exec(function(err, doc) { 
     //find labels 
     labels = _.filter(doc.children, obj => /^\*/.test(obj)); 
     //remove labels from children array 
     children = _.difference(doc.children, labels); 
     //remove label identifier '*' 
     labels = _.map(labels, label => label.substring(1)); 
     self.find({ 
     vendor: vendor, 
     $or: [{ 
      "partcode": { 
      "$in": children 
      } 
     }, { 
      "label": { 
      "$in": labels 
      } 
     }] 
     }, {_id: 0}, callback); 
    }); 
}); 

byłbym zainteresowany w komentarzach. Zwłaszcza w odniesieniu do elegancji, struktury, konwencji itp. Coś tak złego kształtu lub brzydoty, sprawia, że ​​twoje oko się klei?

+0

Czy naprawdę potrzebujesz specjalnej postaci do rozróżnienia? i zastosuj filtr i różnicę, a także skorzystaj z mapy .. możesz to znacznie uprościć, po prostu usuwając znak specjalny. –

+0

opublikował moją własną odpowiedź jako ulepszenie. –

0

obserwuję z OP's self answer,

Tak naprawdę nie potrzebują znak specjalny (*), żeby odróżnić etykietę z pola dziecięcej. Spowoduje to również zmniejszenie używanych operacji macierzy (filter, difference,).

Więc załóżmy, że nie mają szczególny charakter na etykiecie, kolekcja będzie wyglądać następująco:

{"partcode": "Parent1","children": ["label1"]} 

i

[{"partcode": "Child1","label": ["label1"]}, 
{"partcode": "Child2","label": ["label1"]}, 
{"partcode": "Child3","label": ["label1"]}] 

więc następujący kod daje pożądany rezultat:

PartSchema.static('getChildren', function(query, callback) { 
    var self = this, 
    children = [], 
    labels = []; 
    self.findOne(query, {children: 1, _id: 0}) 
    .exec(function(err, doc) { 
// simply find for children in both `label` and `partcode` fields, 
// using whole children array 
      self.find({ 
      vendor: vendor, 
      $or: [{ 
       "partcode": { 
       "$in": doc.children 
       } 
      }, { 
       "label": { 
       "$in": doc.children 
       } 
      }] 
      }, {_id: 0}, callback); 
     }); 
    }); 

Uwaga: To rozwiązanie to applicab le, jeśli pole child w polu nie jest polem w innym doc i na odwrót.

+0

Cześć Naeem, dziękuję za twoją odpowiedź. Obawiamy się, że potrzebujemy specjalnego znaku, aby odróżnić "etykiety" od "dzieci", ponieważ istnieje możliwość, że kody części mają taką samą nazwę jak etykiety. – Terry

Powiązane problemy