NodeJS: Mongoose jak sprawdzić czy podano tablicę w modelu danych?

Opublikowano: 05.04.2022 - tagi: NodeJS MongoDB Mongoose Walidacja Model Tablica JavaScript

W jednym z poprzednich wpisów pisałem o walidacji danych w bibliotece Mongoose.

Dzisiaj opiszę konkretny przypadek: jak sprawdzić, czy przekazano do modelu tablicę, która jest wymagana?

Sprawdzanie tablicy

Załóżmy, że mam taki model danych:

const PostSchema = new Schema({
title: { type: String, required: true },
tags: { type: [String], required: true }
});
const PostModel = mongoose.model('post', PostSchema);

Definiujemy model danych, w którym mamy dwa parametry: title i tags. Oba są wymagane. Przy czym title to zwykły ciąg znaków, a tags to zwykła tablica tekstowa.

Poniżej znajduje się fragment kodu, który sprawdza poprawność danych w modelu i próbuje dodać nowy rekord do bazy danych:

const newEntry = PostModel({ title: 'Some entry' });

const validateErrors = newEntry.validateSync(); 
console.log('validateErrors: ', validateErrors);

try {
  await PostModel.create(newEntry);
} catch(error) {
  console.log('error: ', error);
}

Pytanie: czy metoda validateSync powinna zwrócić jakieś błędy/błąd walidacji? Czy wszystko tutaj jest ok? Do modelu przekazujemy jedno pole: title, które jest wymagane. Nie przekazaliśmy jednak pola: tags, które także jest wymagane. Więc odpowiedź jest prosta! Zwróci błąd walidacji!

To nieprawda. Rekord zostanie dodany do bazy.

Jak to możliwe?

Walidacja wymaganej tablicy

Żeby dowiedzieć się, co się stało, sprawdźmy zawartość bazy danych. Okazuje się, że pole tags to pusta tablica!

Jeśli w modelu danych zdefiniowaliśmy typ tablica i przy tworzeniu rekordu pominiemy to pole, w takim przypadku zostanie umieszczona pusta tablica.

A co zrobić jeśli chcemy jednak wymagać podania tablicy? Prosta rzecz:

...
tags: { type: [String], required: true, default: undefined }

Definiujemy dodatkowe pole: default i ustawiamy je na undefined. Po tej zmianie zostanie zgłoszony błąd walidacji, a rekord nie zostanie dodany do bazy danych.


Blog: Podsumowanie po roku

Opublikowano: 02.04.2022 - tagi: Blog Podsumowanie

Dokładnie 1 kwietnia 2021 uruchomiłem swojego bloga. Z perspektywy czasu uważam, że to był dobry ruch z mojej strony.

Poniżej krótkie podsumowanie:

Regularność

Przed startem założyłem sobie, że będę publikować wpis minimum raz na tydzień. I to mi się udało! Nie twierdzę, że było łatwo. Czasami były momentu zastoju, ale udało mi się to pokonać.

Przed uruchomieniem bloga chciałem uniknąć sytuacji, że po chwili entuzjazmu zapał będzie z czasem maleć. Dzięki prowadzeniu bloga udało mi się zbudować dyscyplinę.

Rozwój

Jednym ze spiritus movens prowadzenie własnego bloga jest zdobywanie nowych umiejętności. Sprawa jest prosta: uczę się czegoś nowego i opisuję to na blogu.

Chcę rozwijać się także, w pisaniu. Wiem, że przede mną długa droga, ale uczenie się nowych rzeczy sprawia mi przyjemność.

W czerwcu dodałem nowy dział: komiksy. Nie potrafię rysować, ale staram się pracować nad swoją kreatywnością poprzez rysowanie zabawnych sytuacji.

Notatnik

Ludzie tworzą blogi z różnych powodów: jedni, bo chcą dzielić się wiedzą inni, żeby zarabiać pieniądze. Ja złapałem się na tym, że sam od czasu do czasu korzystam z własnego bloga!

Spisuję tu różne rzeczy, które są mi przydatne takie jak na przykład: praca z komiksy lub przeczytane książki.


Podsumowanie: Marzec 2022

Opublikowano: 31.03.2022 - tagi: Podsumowanie Marzec 2022 Blog

W marcu opublikowałem 8 wpisów:

Inne:

  1. Jak zbudować dyscyplinę

JavaScript:

  1. NodeJS: Mongoose walidacja danych modelu
  2. Angular: Jak zintegrować frontend i backend za pomocą proxy?
  3. RxJS: Operator from
  4. Jak sprawdzić czy obiekt jest pusty?
  5. RxJS: Operator map

Webstorm:

  1. Podgląd ostatnio edytowanych lub otwartych plików

Opublikowałem także jeden komiks:

  1. It is not a bug, it is a feature!

Przeczytałem trzy książki:

  1. Dzisiaj narysujemy śmierć - Wojciech Tochman
  2. Król - Szczepan Twardoch
  3. Normalni ludzie - Sally Rooney

Przesłuchałem trzy audiobooki:

  1. Sapiens. Od zwierząt do bogów - Yuval Noah Harari
  2. Smartcuts - Shane Snow
  3. Klara i słońce - Kazuo Ishiguro

RxJS: Operator map

Opublikowano: 29.03.2022 - tagi: JavaScript RxJS Operator Pipe

Operator map z RxJS działa bardzo podobnie jak metoda map z klasy Array.

Służy do przekstałcenia wartości wysłanej z obiektu Observable do postaci nam pasującej.

Przykład:

Załóżmy że mamy taką opowiedź z serwera:

{
    success: true,
    items: [
        {
            title: 'Foo',
            value: 1
        },
        {
            title: 'Bar',
            value: 2
        }
    ]
}

Nas interesuje tylko zwartość z items. W takim przypadku możemy skorzystać z operatora map

import { of } from 'rxjs';
import { map } from 'rxjs/operators';

const fakeResponse =
{
    success: true,
    items: [
        {
            title: 'Foo',
            value: 1
        },
        {
            title: 'Bar',
            value: 2
        }
    ]
}

const observable = of(fakeResponse).pipe(
    map(value => value.items)
);

observable.subscribe(console.log);

JavaScript: Jak sprawdzić czy obiekt jest pusty?

Opublikowano: 24.03.2022 - tagi: JavaScript Obiekt

Można to sprawdzić na kilka sposobów:

Sposób 1: Object.keys

const isObjectEmpty = (object) => {
  return !Object.keys(object).length;
}

const emptyObject = {};
console.log('isObjectEmpty: ', isObjectEmpty(emptyObject)); // isObjectEmpty: true

Metoda keys zwraca klucze obiektu, w postaci tablicy. Jeśli tablica nie ma elementów, oznacza to, że obiekt jest pusty

Sposób 2: Object.entries

const isObjectEmpty = (object) => {
  return !Object.entries(object).length;
}

const emptyObject = {};
console.log('isObjectEmpty: ', isObjectEmpty(emptyObject)); // isObjectEmpty: true

Praktycznie to samo, co poprzednio, ale wykorzystujemy tutaj metodę entries, która zwraca tablicę, której wartości są przechowywane w postaci: [klucz, wartość].

Sposób 3: Object.getOwnPropertyNames

Ostatni sposób różni się trochę od dwóch poprzednich. Metody keys i entries sprawdzają policzalne właściwości obiektu. Metoda getOwnPropertyNames zwraca zarówno policzalne i niepoliczalne właściwości obiektu.

Przykład:

const object = {
  price: 100
};
object.title = 'Foo';
Object.defineProperty(object, 'color', {
  value: 'red',
  enumerable: false
});

console.log(Object.keys(object)); // ['price', 'title']
console.log(Object.getOwnPropertyNames(object)); // ['price', 'title', 'color']

Za pomocą metody defineProperty tworzymy właściwość niepoliczalną o nazwie color. Jak widać jest różnica między keys (ale też entries) a getOwnPropertyNames.

Poniżej przykład z użyciem: getOwnPropertyNames:

const isObjectEmpty = (object) => {
  return !Object.getOwnPropertyNames(object).length;
}

const emptyObject = {};
console.log('isObjectEmpty: ', isObjectEmpty(emptyObject)); // isObjectEmpty: true

const object = {
  price: 100
};
object.title = 'Foo';
Object.defineProperty(object, 'color', {
  value: 'red',
  enumerable: false
});
console.log('isObjectEmpty: ', isObjectEmpty(object)); // isObjectEmpty: false

Przy drugiej próbie nasza funkcja zwróci false, ponieważ wykryje niepoliczalną właściwość color.