piątek, 1 listopada 2013

Po polsku czy po angielsku..

W kontekście dzisiejszego Święta wzięło mnie na refleksje i miedzy innymi zastanowiłem się nad słusznością mojego początkowego założenia, żeby pisać bloga głównie po polsku, kontra okazjonalnych postów na blogu anglojęzycznym piczkowski.blogspot.com, dotyczących głównie jakichś wydarzeń międzynarodowych (Google Developer Day, 33rd Degree, itp)

Blog po polsku dotyczący polskich realiów, w których chcąc nie chcąc jestem obecnie osadzony, miał być szansą dla innych Polaków, developerów, biegaczy.. innych osób mniej lub bardziej dotkniętych tematyką, którą poruszam, na lepszy przekaz, czegoś co po angielsku w moim ujęciu mogłoby być zbyt płytkie. W końcu nie władam tym językiem w równym stopniu co polskim.
Z drugiej jednak strony, dlaczego zawężać dostęp do moich wypocin obcokrajowcom zamykając się na być może konstruktywny odzew z ich strony? Czy w dzisiejszych czasach młodzi ludzie nie są wstanie przetrawić tekstu po angielsku? Czy tym bardziej ja który na co dzień wertuje Internet  w poszukiwaniu odpowiedzi na zagwozdki napotykane w pracy nie powinien być w stanie jasno się wyrazić po angielsku?

Być może pora przesiąść się troche z piczkowskipl.blogspot.com na piczkowski.blogspot.com

Jeśli masz swoje osobiste przemyślenia w tym temacie chętnie podyskutuję.

poniedziałek, 28 października 2013

IV Półmaraton Szakala

W niedzielne południe, miły, ciepły jak na październik dzień, odbył się w Arturówku bieg na dystansie 21km.
W taką pogodę ruch na świeżym powietrzu to sama przyjemność.

Po Maratonie Warszawskim troche 'rozluźniłem łyde' więc nie spodziewalem sie cudu, ale zdaje sie ze poszlo nad wyraz dobrze - 01:58:50 (miejsce nr 233), jedynie 39min. 20 sec. pozniej od zwycięzcy :D

Zapisy z Endomondo:


Czytaj więcej na http://szakalebalut.pl/node/279

poniedziałek, 30 września 2013

35 Maraton Warszawski (2013)

Mój osobisty debiut zakończony powodzeniem. Pogoda dopisała znakomicie. Przyjemnie było w słoneczny niedzielny poranek zrobić 42 kilometrową przebieżkę ulicami Warszawy w towarzystwie tysiąca innych zapaleńców.





Kilka minut po godz. 9.00 zgraja uczestników wyruszyła spod Stadionu Narodowego. Do 20km dawałem radę bez przystanków na picie/jedzenie/siku. Na 20km a potem na 30km i 35km już nie przesadzałem i łykałem trochę PowerRade, wody i przegryzałem banana. Wszystko to dostarczone przez organizatorów. Poza tym co parę kilometrów na trasie słychać było zagrzewające do walki zespoły różnej maści - bębny, saksofon, rock, reggae, gospel.. dla każdego coś miłego.
Na ok. 35km zaczęły się schody - ucisk na stawach kolanowych, odrętwienie i ból nóg, każdy krok powodował ból. Kondycji, sił i chęci jeszcze miałem sporo, ale nogi już nie dawały rady. Trochę pomagał postój na wodopojach, raz też zatrzymałem się żeby rozciągnąć nogi na ok. 38km. Potem już tylko walka żeby nie zatrzymać się, żeby ciągle biec i żeby to się już skończyło :) Ogólnie polecam, wrażenia niezapomniane, szczególnie doping kibiców przy trasie, ludzi w różnym wieku i narodowości.
Moją trasę nagraną Endomondo można przejrzeć tutaj:



Z oficjalnych wyników:



Miejsce
7068
Nr startowy
2383
Kat. wiekowa
30
Miejsce w kat. wiekowej
2635
Czas netto
04:39:24
Czas brutto
04:53:01
Miejsce brutto / netto
6415-6288
5km
00:32:37
10km
01:04:18
15km
01:35:56
20km
02:07:29
21km
02:16:11
25km
02:39:15
30km
03:12:44
35km
03:47:36
40km
04:24:06

Wszystkie wyniki są tutaj



Więcej zdjęć i informacji na stronie: http://pzumaratonwarszawski.com

niedziela, 1 września 2013

Biegowa Bitwa o Lodz

W sobote 27go lipca 2013 r. odbyła się druga Biegowa Bitwa o Łódź.
Start i meta znalazły się przy krańcówce lini autobusowej nr 51 w Łagiewnikach.
Trasa długości 12 km urozmaicona atrakcjami. Już na początku szlauch strażacki z zimną wodą dla ochłody. To akurat chyba najprzyjemniejszy element programu biorac pod uwagę temperaturę.
Potem pare przeszkód w postaci ławeczek, zwalonych drzew pod którymi trzeba było sie przeczołgać, mordercze podbiegi i zbiegi, rów z wodą, do którego zjeżdżało sie z nasypu, więc chcąc nie chcąc każdy musiał się skompać po szyję w gnojówce :) Potem jeszze pare podbiegów i zbiegów, czołganie, przeskoki przez skrzynie, bieg przez opony i kółeczko z jedna oponą na grzbiecie a potem jeszcze 500m, czołganie sie przez tunel z materiału i meta.

Fotki, filmy i inne relacje można znaleść tu:
http://biegampolodzi.pl/biegowa-bitwa-o-lodz


poniedziałek, 19 sierpnia 2013

IV Triatlon Siedlecki

18 sierpnia 2013 odbył się IV Triatlon Siedlecki. Pogoda dopisała a wręcz było zbyt słonecznie i parno.
Na miejscu pojawiłem się przed 12.00 po czym wspólnie z kolega objechaliśmy parę razy trasę rowerowa za każdym razem gubiąc właściwą drogę. Właściwie nikt z organizatorów nie był w stanie wskazać właściwej drogi ale nic to, bo w czasie zawodów trasa była już dobrze oznaczona i nie można było się zgubić.

Po 13.00 wstawiliśmy rowery do boksów i trochę zestresowani oczekiwaliśmy na start. Dla mnie i kolegi był to pierwszy triatlon wiec niemałe emocje.
O 15.00 zaczęło się. Wystartowaliśmy z linii pierwszej boi. Brzmi jakby było to daleko od brzegu ale w rzeczywistości przy samej boi dotykałem nogami dna.

W wodzie znalazło sie ok 150 uczestników wiec było trochę tłoczno ale powoli udało sie wyminąć kilka osób. Atmosfera rywalizacji sprawiła ze nim sie spostrzegłem juz bylem przy drugiej boi, którą trzebabylo opłynąć z prawej i z powrotem do pierwszej boi. Poszło całkiem sprawnie. Wszystkich uczestników miałem nagle po prawej stronie i mogłem swobodnie płynąc przed siebie przez nikogo nieblokowany.

Wybieg z wody, parę zasapanych oddechów przy boksie z rowerem. Wycieram szybko stopy, wciągam skarpety i buty biegowe, wciągam kaszulke z uprzednio przypiętym numerem startowym, zapinam kask, biorę rower i gnam na trasę.

Rower po pływaniu to kolejna cześć triatlonu co do której miałem obawy (nie tak duże, jak co do pływania, bo nigdy nie pływałem zbyt wiele na otwartym akwenie) gdyż mój rower jest juz trochę wysłużony i na około tygodnia przed startem odkryłem ze support potrafi mi przeskakiwać przy zbyt dużym nacisku na pedał. Na naprawę nie było zbytnio czasu. Wolałem juz jechać na takim jak jest z nadzieja ze jakoś to będzie niz rozgrzebać rower na części i nie mieć w ogole na czym pojechać. Jak sie okazało potem na trasie przede mną trafił sie zawodnik który miał dokładnie ten sam problem. Na grząskim piachu słychać bylo tylko trzaski przeskakującego suportu i widać zawodnika kręcącego pedałami w miejscu. Całe szczęście ze wymieniłem opony na grubsze 2.1 cala bo z cienkimi na takim piachu byłoby trudno, chociaż widziałem parę rowerów z oponami na oko 1-1.5 cala.

Jakos udało sie przejechać na tak zwalonym rowerze 2 kolka po 5 km. Na pierwszym zaliczyłem glebe na zakręcie, kiedy to rozpędzony ugrzązłem przednim kołem w muldzie piachu i przeleciałem przez kierownice, na szczęście na ręce a nie nosa. Szybko sie zwlekłem nie tarasując zbytnio ruchu i pognałem dalej, trochę biegnąc po piachu z rowerem, trochę jadąc.
Najlżejsza cześć dla mnie to ostatnia część - bieg 3km. tutaj nie było już problemow sprzętowych ani obawy ze się utopie :) Poszło gładko. Sam się dziwie ale udało mi się uplasować na pozycji 62 z czasem o 18 minut późniejszym od najszybszego uczestnika.
Kolejne moje czasy na odcinkach to:

pływanie (400m): 00:09:40
rower pierwsza pętla (5km): 00:37:23
rower druga pętla (5km): 00:14:31
bieganie (3km): 00:18:05




 

Ogólnie jestem bardzo zadowolony, za rok poprawie wyniki :)

Wyniki:
http://www.maratonczyk.pl/wyniki_2013/triathlon_siedlecki_open_18.08.2013.pdf


Zdjęcia z imprezy:
http://www.spin.siedlce.pl/2013/08/18/iv-triathlon-siedlecki/

Inne relacje:
http://akademiatriathlonu.pl/newsy/aktualnosci/wydarzenia/1507-iv-triathlon-siedlecki-czyli-debiut-sprinterki-na-dystansie-sprinterskim


wtorek, 23 lipca 2013

MongoDB 10gen DB Admin

Idąc za ciosem po ostatnim kursie dla Java developerow przejrzałem też ostatni kurs dla DB Adminów i poza powtórką większości rzeczy znalazłem też pare ciekawostek, np: o komendach:





Web admin page:

Wyjasnienie write concern i cluster-wide commit:
Rekomendowane konfiguracje:



Uzywanie Mongo Profiler:


show profile
db.setProfilingLevel(2) // operacje trwajace ponad 100ms
db.setProfilingLevel(1,3) // operacje trwajace ponad 3ms
db.system.profile.find().sort({$natural: -1}).limit(1).pretty() // last profile entry
db.getProfilingStatus()
db.system.namespaces.find() // info o kolekcjach

mongostat [--port <port number>]
mongotop [--port <port number>]

Pokaż aktywne operacje z ich statystykami:
db.currentOp()
db.killOp(<opid>) // zabicie operacji po id

Kommpaktowanie kolekcji:
db.runCommand ( { compact: '<nazwa kolekcji>', force:true})


Mongo Security:

> use admin
> db.addUser('the_admin','password')

mongo localhost/admin -u the_admin -p password

> db.system.users.find()





Backup:

- mongodump [--db dbname] [--oplog] / mongorestore [--oplogReplay]
- kopia plikow 'data' systemowych (shutdown server, kopia plików) - baza musi byc 'journaling enabled'. Pomocne jest db.fsyncLock() / db.fsyncUnlock() lub jesli backupujemy sharded cluster:
sh.stopBalancer() / sh.startBalancer()

Kolejny kurs ukonczony z dobrym wynikiem 96% z egzaminu koncowego:


i kolejny tez nienajgorzej:



poniedziałek, 17 czerwca 2013

Startup Weekend Lodz 2013

Pierwsze tego typu wydarzenie w Lodzi ale kolejne z kolei w historii. Ludzie z roznych dziedzin spotkali sie w ten weekend w Lodzi, aby wspolnie zrealizowac niezwykle pomysly. Niektórzy przyszli ze swoimi pomysłami, inni przyszli nawiązać nowe znajomości, jeszcze inni pokodować itd.
Ostatecznie spośród wszystkich pomysłów do realizacji zostało wybranych 6:

Creative Learning ! Platforma edukacyjna i rozrywkowa dla dzieci. Oferujemy 2 opcje: 1) aplikacje zajmujące i uciszające dzieci (wyjdą pierwsze!) & 2) aplkaje interaktywne dziecko-dziadek, dziecko-rodzic ( któtkie i proste aplikacje przyciągające dzieci z pomocą rodzica lub dziadka).
Zabawne, kreatywne, edukacyjne i estetyczne aplikacje, o to chodzi w Creative Learning - aplikacje które staną się legendą dziecięcych gier. Jeśli chcesz by Twoje dziecko uczyło się nowych rzeczy i jednocześnie bawiło śledź naszą stronę i FB. Pomóż nam testować produkt i spodziewaj się ich wkrótce na iTunes & Google Play.
- Creative Learning - SHAPES
- Creative Learning - LETTERS
- Creative Learning - NUMBERS
-Creative Learning - ANIMALS
i więcej!
http://www.creative-learning.eu/


Photo: http://www.creative-learning.eu/



allSpotted! - team stworzy aplikację mobilną na FaceBook-owy rych Spotted ( anonimowej komunikacji pomiędzy użytkownikami przebywającymi w tym samym miejscu). Pozwoli ona znaleść ponownie osobę spotkana czy widzianą ale do której nie masz kontaktu. Aplikacja używa ruch na forach społecznościowych i informację GPS.

Photo: allSpotted


Space Lawyer! Najlepsze serwisy prawnicze online, wszędzie i o każdej porze.

Photo: Space Lawyer


ADS ON PETS! Dajemy firmom nowy kanał komunikacji. Przez danie możliwośći miłośnikom zwierząt wyróżnienie się ich pupili, dajemy im też możliwość zarobienia, żeby jeszcze bardziej mogli 'rozpuszczać' swoje pociechy.

Photo: ADS ON PETS


Video Pediatric Advice! Platforma, która pozwala pediatrom dawać porady pacjentom przez kamerę.

Photo: Video Pediatric Advice


"Gamming for Cats and feed it"
Idea jest całkiem prosta, kot gra na Ipadzie, jeśli zdobędzie 100 punktów dostanie jedzenie.
W planach rozwoju jeśli przećwiczy 200 kkalori dostaje większą porcję !.

Photo: Dzisiaj skończyliśmy prototyp urządzenia "Gamming for Cats and feed it"

Idea jest całkiem prosta, kot gra na Ipadzie, jeśli zdobędzie 100 punktów dostanie jedzenie.

W planach rozwoju jeśli przećwiczy 200 kkalori dostaje większą porcję !.

Aplus - to jeden z pomysłów ze startup weekendu. Naucz się matematyki Online. Kamil Kamiński odpowie na wszystkie Wasze pytania z matmy ONLINE.

Photo: Aplus - to jeden z pomysłów ze startup weekendu. Naucz się matematyki Online. Kamil Kamiński odpowie na wszystkie Wasze pytania z matmy ONLINE.

Ostatecznie do Kaliforni jedzie Dominik z Creative Cats i karmnikiem dla kotów.
2 miejsce - nasz team z serwisem prosteumowy.pl
3 miejsce  -  allSpotted oraz Video Pediatric Advice!


Media:
http://moya.toya.net.pl/site_aktualnosci.php?news_id=4708&s=6c6d4ca73d8dabf0b3e6558c4704d4b6
http://moya.toya.net.pl/site_aktualnosci.php?news_id=4708&s=6c6d4ca73d8dabf0b3e6558c4704d4b6





wtorek, 11 czerwca 2013

Dzem malinowy

Wczoraj dotarla do mnie zamowiona na Allegro malinka. Swieża i pachnaca nowoscią Raspberry Pi. Dzis postawnowilem ja wypróbowac.
Zgodnie z tutorialem na stronie zbootowalem system po podlaczeniu tego malego cuda do telewizora.
Uprzednio zainstalowalem na karcie SD 4GB obraz "New Out of Box Software".

Po podlaczeniu zasilania obraz zbootowal sie bezproblemowo, wykryl klawiature i odpalil UI graficzny z wyborem systemu do instalacji.

Wybralem instalacje zalecaną - Raspbian



OK, wszystko fajnie, tylko brakuje mi monitora a sleczenie przy telewizorze za kazdym razem jest malo wygodne, dlatego potrzebowalem skonfigurowac polaczenie SSH.

Tu pojawil sie drobny klopot. Mam w domu router DHCP ale jak znalesc jaki adres IP zostal przydzielony Raspberry Pi?
Z pomocą przyszlo narzędzie nmap

Na innym kompie z Ubuntu podlaczonym do tej samej sieci odpalam:

nmap -sP 192.168.1.0/24
 
i otrzymuje:

Starting Nmap 6.00 ( http://nmap.org ) at 2013-06-11 17:45 CEST
Nmap scan report for 192.168.1.1
Host is up (0.00082s latency).
Nmap scan report for 192.168.1.103
Host is up (0.061s latency).
Nmap scan report for 192.168.1.105
Host is up (0.00011s latency).
Nmap scan report for 192.168.1.106
Host is up (0.00065s latency).
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.65 seconds

Przy okazji, podobny efekt mozna uzyskac na Windows uzywajac:

arp -a

otrzymuje:

Interfejs: 192.168.1.104 --- 0xf
  Adres internetowy      Adres fizyczny      Typ
  192.168.1.1           00-22-6b-fb-a3-17     dynamiczne
  192.168.1.103         78-d6-f0-65-4e-a7     dynamiczne
192.168.1.105 14-da-e9-11-6f-93 dynamiczne 192.168.1.106 00-0b-81-87-d8-b9 dynamiczne



Dostalem wiec adresy 3ch urzadzen, tylko ktore z nich to RPi ? Jedyne wyjscie jakie znalazlem to sprawdzenie IP na dwóch pozostałych i dojscie do rozwiazania droga eliminacji.

Następnie:

ssh pi@192.168.1.106

i jestem podłączony w trybie 'headless' tyle ze kablem.

Fajnie byloby sie poczuc wireless :)

Nie ma problemu, trzeba tylko zakupic male urządzonko - koncowke usb wifi na chipsecie Realtek RTL8188CUS. Nastepnie postępujemy dokladnie tak jak w linku:

Zmieniamy zawartość pliku
/etc/network/interfaces
tak jak poniżej:

auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0

auto wlan0

iface wlan0 inet dhcp
wpa-ssid “XXXXXX-XXXXXX”
wpa-psk “XXXXXXXXX”


gdzie XXXX w wpa-ssid  to nazwa naszej sieci WIFI a XXXXX w wpa-psk to hasło do sieci.


Teraz przydałoby się przekierować display z RPi na Ubuntu zeby troche sobie poklikac w Raspbianie.

Nic prostszego pod Ubuntu.
Najpierw pozwalamy Ubuntu akceptowac polaczenia z zewnatrz

sudo xhost +

sprawdzamy swoje IP:

ifconfig
          wlan0     Link encap:Ethernet  HWaddr 10:0b:a9:ca:23:78
          inet addr:192.168.1.106  Bcast:192.168.1.255  Mask:255.255.255.0

logujemy sie przez ssh do Raspberry i przeierowujemy display:

ssh -XY pi@192.168.1.107
export DISPLAY=192.168.1.106:10

gotowe, teraz np mozemy uruchomic konfigurator ustawien:

sudo raspi-config

Jesli chcesz dowiedzieć sie co jeszcze możesz zrobić, zerknij na mój angielski blog: 
http://piczkowski.blogspot.com/2013/11/raspberry-magic.html
http://piczkowski.blogspot.com/2013/11/rspberry-pi-webcam.html





wtorek, 5 marca 2013

Indie 04.2013


W tym roku pora na Indie. Wyjazd firmowy na tydzien ale potem daje sobie jeszcze jeden tydzien na zwiedzanie.
Co przed wyjazdem? W pierwszej kolenosci wiza, na ktora sie czeka do 3 tyg.
Wymagane dokumenty to*:
1. Wniosek wizowy wypelniany online i drukowany
2. List polecajacy z firmy (w przypadku wizy biznesowej
3. Zaproszenie z firmy w Indiach (w przypadku wizy biznesowej)
4. Zdjęcie paszportowe  (3,5 x 4,5cm)
5. Oryginal paszportu
6. Kopia biletu lotniczego lub rezerwacji (w obie strony)

Do tego przy skladaniu wniosku nalezy uiscic oplate eg. cennika:
Lp.Rodzaj wizyOpłatawizowa (PLN)ICWFOpłata z tytułu kosztów obsługi BLS (w PLN)Całkowity koszt (w PLN)
1Wiza turystyczna1848 40 232
2Wiza biznesowa6678 40 175


*informacje zaczerpniete ze strony Ambasady Indii

Wiecej wiesci z planowania podróży i pobytu niebawem...

czwartek, 28 lutego 2013

Konkurs OneWebSQL

Ostatnimi czasy zajmuje sie glownie budowaniem mojego ego :))
Pierwszy raz od dawien dawna udalo mi sie nawet cos wygrac
http://onewebsql.com/konkurs-spring
http://e-point.pl/co-nowego?news_id=1500144,rozstrzygniecie-konkursu-na-najlepsza-aplikacje-webowa

Zaproponowane przeze mnie rozwiazanie jest upublicznione na githubie. Przyznam szczerze ze zmienilbym w nim jeszcze pare rzeczy, glownie zwiazanych z warstwa widoku. Najlepiej przepisal JSP na AngularJS.

wtorek, 26 lutego 2013

MongoDB 10gen Kurs


Kurs wystartował kolejny raz.
Przeszedłem instalacje MongoDB, podstawowe query z mongo shell i aplikacji Javowej.
Poznałem Spark Micro Web Framework i FreeMarket templaty.
Jak narazie OK, niezbyt trudne cwiczenia do przejscia w jedną noc.

Założyłem projekt github na potrzeby szkolenia https://github.com/piczmar/MongoDB4JavaDev/

2 czesc kursu
to podstawy CRUD i zapoznanie z Mongo Shell - interaktywna konsola dostepu do bazy, ktora jest interpretorem JavaScript.
Przydatne skroty klawiszowe:
- przywolanie ostatniej komendy: strzalka do gory
- przeskoczenie na poczatek linii: CTRL+A
- przeskoczenie na koniec linii: END
- dokonczenie polecenia/metody: TABrepli

Przydatne komendy:
help -  wyswietla liste komend
help keys - wyswietla skroty klawiszowe

Mozna wykonywac pliki json z konsoli, np stworzmy plik o nazwie popAvg.json ktory chcemy wykonac na bazie o nazwie week5


use week5
db.zips.aggregate([{

$group:{
_id:'$state',
average_pop:{$avg:'$pop'}
}
}])

plik mozemy uruchomic:
mongo < popAvg.json



Zapoznanie z podstawami JavaScript, np definiowanie obiektow i odwolywanie sie do ich wlasnosci:
x = {a:"test"} // tworzy nowy obiekt
x.a // odwolanie do atrybutu a jako literalu
z="a"
x[z] //odwolanie do atrybutu jako wartosci slownikowej (ang. dictionary) klucz : wartość

Mongo zapisuje obiekty w formacie BSON
Podstawowe typy danych:
NumberInt - integer 32bity
NumerLong - integer 64bity
ISODate - date, new Date() tworzy ten typ danych


Zapisywanie obiektow:
db - zmienna trzymajaca aktualna baze
db.nazwa - kolekcja o nazwie 'nazwa' w bazie, zeby do niej zapisac nalezy wykonac metode insert np:
db.nazwa.insert(doc)
Wyszukiwanie:
db.people.find() - zwraca wszystkie obiekty, jesli podamy kryteria wyniki beda przefiltrowane, np:
db.people.find({name:"John"})
db.scores.find({score:200}).pretty() - wyswietla sformatowany wynik
db.people.findOne() - zwraca pierwszy lepszy rekord z kolekcji jesli nie podamy kryteriow, drugi argument po kryteriach prezycuje jakie pola chcemy w wyniku

> db.people.findOne({name:"Smith"})
{ "_id" : ObjectId("513ba7e947631d66ce571e99"), "name" : "Smith" }
> db.people.findOne({name:"Smith"},{"name":true, "_id":false})
{ "name" : "Smith" }

Wypisanie obiektu jako json:
var obj = db.people.findOne()
printjson(obj)

Wyszukiwanie za pomoca wyrazen:
 db.scores.find({score:{$gt:10, $lte:20}}) - znajdz rekordy ktorych  'score'>10 && 'score'<20


Kryteria uzywaja porownania leksygraficznego tzn ze jesli w tej samej kolekcji pole jest typu string dla jednego rekordy a typu numerycznego dla innego i w kryterium uzywamy porownania dla stringow to rekordy w ktorych to pole nie jest stringiem sa w ogole pomijane.

Mozna tez przefiltrowac rekordy ktore maja dany atrybut, np:
db.people.find({profession: {$exists: true}}) - zwraca tylko te rekordy ktore maja atrybut 'profession'

lub atrybut okreslonego typu:
 db.people.find({profession: {$type: 2}}) - rekordy z atrybutem 'profession' typu string, numery dla typow sa zdefiniowane w specyfikacji BSON

lub uzyc wyrazenie regularne:
db.people.find({name: {$regex: "m$"}}) - tylko rekordy ktorych 'name' konczy sie na litere 'm'
db.people.find({name: {$regex:'q'}})- rekordy ktorych 'name' zawiera litere 'q'
Unia OR:
db.people.find( { $or: [{name:"Adam"}, {profession:{$lte:"programmer"}}] })

Koniunkcja AND:
db.people.find( { $and: [{name:{$gt:"C"}}, {name:{$regex:"a"}}]}) - mozna to zapisac prosciej jako:
db.people.find( { name:{$gt:"C", $regex:"a"} })

Kryteria dla kolekcji

{ "_id" : ObjectId("513bb7374802e675111ba1c9"), "name" : "Howard", "favourites" : [ "pretzels", "beer" ] }


db.accounts.find({favourites:{$in:["pretzels", "chease"]}}) - wrzystkie rekordy zawierajace w polu 'favourites' wartosci 'pretzels' lub 'chease'
db.accounts.find({favourites:{$all:["pretzels", "chease"]}}) - wrzystkie rekordy zawierajace w polu 'favourites' wartosci 'pretzels' i 'chease' w dowolnej kolejnosci

Kryteria dla zagnieżdżonych dokumentow:

{ product : "Super Duper-o-phonic", 
  price : 100000000000,
  reviews : [ { user : "fred", comment : "Great!" , rating : 5 },
              { user : "tom" , comment : "I agree with Fred, somewhat!" , rating : 4 } ],
  ... }

db.catalog.find({price: {$gt:10000}, "reviews.rating": {$gte:5}}) - zwraca wszystkie produkty z price > 10000 i rating >=5

metoda find() zwraca kursor ktory ma metody: hasNext() i next() przydatne do nawigowania po wynikach, np:
> cur = db.people.find(); null; // null jako druga komenda zapobiega drukowaniu wyniku
> cur.limit(5); null; // limit do 5 rekordow
> cur.skip(2); null; // pomiń 2 recordy z wyniku
> cur.sort({name: -1}); null; // sortuj wynik po 'name' w odwrotnym porządku leksykograficznym
> cur.hasNext()
> cur.next()


Liczenie recordow:
db.scores.count({type:"essay", score: {$gt:90}})

Update:
 db.people.update({name:"Adam"}, {profession: "seller"}) - update bierze 2 argumenty, 1: query, 2: nowe wartosci pól, pola pominiete zostana usunięte z dokumentu

np.:

{ "_id" : "Texas", "population" : 2500000, "land_locked" : 1 }


db.foo.update({_id:"Texas"},{population:30000000})
wynik: { "_id" : "Texas", "population" : 30000000 }


Inny sposob ktory modyfikuje tylko wybrane pola:
db.foo.update(_id:"Texas", {$set: {population: 30000}})
lub inkrementacja:
db.foo.update(_id:"Texas", {$inc: {population: 1}})

Jesli nie podamy kryterium to domyslnie zostanie updatowany pierwszy znaleziony a nie wszystkie jak to jest w SQL. Zeby updatowac wszystkie trzeba podac dodatkowy argument {mutil:true}

db.people.update({}, {$set:{title:"Dr"}}, {multi : true})
db.people.update({}, {$set:{title:"Dr"}}, {upsert : true}) //updatuje istniejace dokumenty lub utworzy nowy jesli nie znalazl dokumentow do updatowania

Iindywidualny dokument jest updatowany atomowo, ale Mongo nie wspiera izolowanych tranzakcji przy updacie wielu dokumentow na raz.


Usuwanie pol:
db.foo.update(_id:"Texas", {$unset: {population: 1}})

Operatory tablicowe:

$push, $pop, $pull, $pushAll, $pullAll, $addToSet

np:

> db.arrays.insert({_id:0, a:[1, 2, 3, 4]}) //tworzymy nowy obiekt z tablicą 'a'
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 1, 2, 3, 4 ] }
> db.arrays.update({_id:0}, {$set: {"a.2":5}}) //zmien element tbalicy o indeksie 2
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 1, 2, 5, 4 ] }
> db.arrays.update({_id:0}, {$push:{a:6}}) //dodaj nowy element na koniec tablicy
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 1, 2, 5, 4, 6 ] }
> db.arrays.update({_id:0}, {$pop:{a:1}}) //usun element z konca tablicy
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 1, 2, 5, 4 ] }
> db.arrays.update({_id:0}, {$pop:{a:-1}}) // usun element z poczatku tablicy
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 2, 5, 4 ] }
> db.arrays.update({_id:0}, {$pushAll:{a:[7,8,9]}}) // dodaj kilka elem. na koniec tablicy
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 2, 5, 4, 7, 8, 9 ] }
> db.arrays.update({_id:0}, {$pullAll:{a:[7,8,9]}}) //usun wszystkie elementy jak podane w liscie
^[db.arrays.findOne()
{ "_id" : 0, "a" : [ 2, 5, 4 ] }
> db.arrays.update({_id:0}, {$pull:{a:5}}) // usun pojedynczy element
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 2, 4 ] }
> db.arrays.update({_id:0}, {$addToSet:{a:5}}) // dodaj nowy element jesli jeszcze nie istnieje
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 2, 4, 5 ] }
> db.arrays.update({_id:0}, {$addToSet:{a:5}}) //dodaj nowy element jesli jeszcze nie istnieje
> db.arrays.findOne()
{ "_id" : 0, "a" : [ 2, 4, 5 ] }


Usuwanie rekordow: 
db.people.remove({}) //usuwa wszystkie dokumenty z kolekcji, jeden po jednym
db.people.drop() //usuwa wszystkie dokumenty z kolekcji bardziej efektywnie niz powyzsze remove({}) bo nie pojedynczo tylko cala kolekcje
db.people.remove({name: "Adam"}) // usuwa dokumenty spelniajace okreslone kryteria

Usuwanie wielu rekordow nie jest atomowe, ale pojedynczego juz tak. Zaden reader nie zobaczy dokumenty Mongo w polowie usunietego.

Jak sprawdzic czy ostatnio wykonana operacja przebiegla poprawnie czy nie: 

db.runCommand({getLastError: 1})
przyklad wyniku:
{
"err" : "E11000 duplicate key error index: test.people.$_id_  dup key: { : \"Smith\" }",
"code" : 11000,
"n" : 0,
"connectionId" : 3,
"ok" : 1
}

To samo co w konsoli mozemy zrobic przy użyciu Java API, demo dostepne na githubie.

W dalszej czesci kursu bedziemy budowac aplikacje webowa. Zasa dzialania zostala opisana na filmie:





Tydzien 4 dotyczy wydajnosci bazy i indeksow jako podstawowego elementu wplywiajacego na wydajnosc podczas przeszukiwania bazy.
Porzyteczne narzedzia do profilowania w Mongo to:
z konsoli Mongo:
db.getProfilingStatus() - zwtaca aktualny status logowania
db.setProfilingLevel(1,3) - poziom logowania 1, trwajace dluzej niz 3ms, dostepne poziomy:
0 - logowanie wylaczone
1 - pokazuj tylko wolne operacje
2- pokazuj wszystkie operacje
Logi sa zapisywane do db.system.profile i moga byc przeszukiwane np:
db.system.profile.find({millis:{$gt: 1000}}).sort({ts:-1})

programy ktore sa instalowane razem z mongo:
mongotop - dostarcza statystyki na poziomie kolekcji mowiace ile Mongo spedza czasu na operacjach zapisu/odczytu




mongostat -statustyki operacji mongo zwlaszcza pozyteczne - wykorzystanie indeksow





Tydzien 5:

Agregacje w Mongo.
W SQL odpowiednikiem jest GROUP BY.
Zalozmy ze mamy kolekcje car zawierajaca dokumenty:
{name: 'car', price: '12}
{name: 'car', price: '2'}


> db.manuf.aggregate([{$group: { _id:'$name', num_car:{$sum:1}}}])
{ "result" : [ { "_id" : "car", "num_car" : 2 } ], "ok" : 1 }
dostajemy w wyniku liczbe dokumentow z name='car'

jesli chcielibysmy zsumowac ceny w grupie:

> db.manuf.aggregate([{$group: { _id:'$name', prices:{$sum: '$price'}}}])


Elementy pipline aggregacji:
$project - wybiera ktore atrybuty chcemy w wyniku
$match - filtruje kolekcje po jakims kryterium, jak WHERE w SQL
$group - grupuje wynik poprzedniego kroku pipeline
$sort - jak ORDER BY w SQL, sortuje wynik
$skip - omija iles poczatkowych rekordow
$limit - ogranicza wynik do iluś rekordow.
$inwind - normalizuje dane, jesli dokument ma tablice 3 rekordow to inwind utworzy 3 oddzielne dokumenty z jednym elementem tablicy

Compound grouping by multiple group:
mamy dokumenty:

{ "_id" : ObjectId("5154ba3f7b1fda1c6b22429b"), "category" : "drive", "name" : "car", "price" : 12 }
{ "_id" : ObjectId("5154ba437b1fda1c6b22429c"), "category" : "drive", "name" : "car", "price" : 23 }
{ "_id" : ObjectId("5154bf547b1fda1c6b22429d"), "category" : "drive", "name" : "bike", "price" : 10 }
{ "_id" : ObjectId("5154c1247b1fda1c6b22429e"), "category" : "swim", "name" : "canoo", "price" : 100 }
{ "_id" : ObjectId("5154c12f7b1fda1c6b22429f"), "category" : "swim", "name" : "boat", "price" : 101 }


db.manuf.aggregate([{$group:{_id:{name:'$name',categ:'$category'},sum:{$sum:1}}}])

dostaniemy:
{
"result" : [
{
"_id" : {
"name" : "boat",
"categ" : "swim"
},
"sum" : 1
},
{
"_id" : {
"name" : "canoo",
"categ" : "swim"
},
"sum" : 1
},
{
"_id" : {
"name" : "bike",
"categ" : "drive"
},
"sum" : 1
},
{
"_id" : {
"name" : "car",
"categ" : "drive"
},
"sum" : 2
}
],
"ok" : 1
}

Inne wyrazenia uzywane w grupowaniu:
$sum
$avg
$min
$max
$push
$addToSet
$first - uzywane z sort, daje pierwszy dokument
$last - uzywane z sort, daje ostatni dokument


Przyklady zastosowania niektorych operatorow na githubie.

Ograniczenia aggregacji:
- rozmiar wyniku ograniczony do 16MB (jako że wynik jest pojedynczym dokumentem)
- nie mozna uzyc wiecej niz 10% pamieci maszyny
- sharding: kolekcje sa na rozych nodach klastra, po pierwszym pipe $sort lub $group wynik musi byc zwrocony na klienta (tam gdzie dziala process 'mongos')

Jesli z powodu tych ograniczen nie mizna uzyc agregacji mozemy zamiast tego uzyc:
- mapreduce
- hadoop (jest konektor do mongo)


Week 6: replication

Tworzenie klastra na pojedynczej maszynie - koniecznie na roznych portach, normalnie stworzylibysmy na roznych serwerach:

1. tworzymy foldery danych dla 3ch replik:
mkdir c:\data\rs1
mkdir c:\data\rs2
mkdir c:\data\rs3

mongod --replSet rs1 --logpath "1.log" --dbpath c:\data\rs1 --port 27017
mongod --replSet rs1 --logpath "2.log" --dbpath c:\data\rs2 --port 27018
mongod --replSet rs1 --logpath "3.log" --dbpath c:\data\rs3 --port 27019
re
wszystie sa czescia tego samego zbiory replik rs1

Tworzymy konfiguracje dla zbioru w pliku init_replica.js:



config = { _id: "rs1", members:[
          { _id : 0, host : "localhost:27017", priority:0, slaveDelay:5},
          { _id : 1, host : "localhost:27018"},
          { _id : 2, host : "localhost:27019"} ]
};

rs.initiate(config);
rs.status();


Plik ten ladujemy do jednego z wezlow:
mongo --port 27018 < init_replica.js

Teraz laczymy sie do jednego z nodow i drukujemy status
mongo --port 27018

rs.status()


Mozemy sie polaczyc do jednego z SECONDARY node i sprawdzic ze nie mozemy do nich pisac, tylko mozna pisac do PRIMARY.

Jesli chcemy czytac z SECONDARY musimy najpierw powiadomic go o tym i po polaczeniu sie do niego wywolac:
rs.slaveOK()


rs.isMaster() - sprawdzenie czy node do ktoredo sie zalogowalismy jest MASTERem

Jak sprawdzic co sie dzieje podczas replikacji? Mamy w tym celu kolekcje oplog.rs:

use local
show collections



Tydzien 6. Sharding

Co to jest sharding? Jest to dzielenie kolekcji na wiele serwerów.





Po polaczeniu do mongo konsoli na domyslnym porcie ('mongo') mozemy sprawdzic status sharda:

sh.status()

oraz informacje o shardowanej kolekcji:

db.grades.stats()

Kazdy dokument miec shard key.
Shard key jest niezmienny.
Indexy musza sie zaczynac od shard key, np jesli jest shard key 'student_id'
to pozostale indeksy np:
(student_id, class)
(student_id, name)
Przy zapytaniach jesli nie uzyjemy shard key to zapytanie bedzie rozpropagowane na wszystkie nody w klastrze zamiast do poprawnego sharda.




Egzamin koncowy zdany na 95%, chyba powinienem czuć sie MongoDB expertem, jednak czuje ze ta wiedza szybko wyparuje jeśli nie będę jej używać.

sobota, 23 lutego 2013

Wykonanie SQLi przy starcie aplikacji Grails

Jak wrzucic do Grails dataSource zdefiniowanego w DataSource.groovy jakies dane wykonujac skrypty SQL?
1. Dodaj nowy plik grails-app/config/spring/resources.xml a w nim:

    <jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
        <jdbc:script location="classpath:/com/initdb/data.sql" />
        <jdbc:script location="classpath:/com/initdb/data2.sql" />
    </jdbc:initialize-database>


2. Umiesc skrypty zdefiniowane w kroku 1. w class path, czyli stworz nowy folder w src/java lub src/groovy

com/initdb

 i dodaj w nim swoje skrypty SQL: data.sql, data2.sql

sobota, 12 stycznia 2013

Code Retreat Warszawa 2013

Swoj drugi w zyciu code retreat minął pomyślnie. Bylo ciekawie i owocnie. W odróżnieniu od pierwszego code retreat ktory skupiał sie na czystej Javie i TDD tym razem rozwijalismy aplikacje w Androidzie.
Od czasu kiedy uczylem się Androida i pisalem pierwsze aplikacje na tą platforme minęło kilka lat. Nic dziwnego ze w tym czasie wiele sie zmieniło w kwestii narządzi deweloperskich. Pomysł pokazania w jaki sposob Groovy moze zaistniec na tym polu przynajmniej dla mnie była trafiona.
Chłopaki z Polidea zrobili kawal dobrej roboty integrujac Roboelectric ze Spockframework z czego powstalo RoboSpock. Co więcej, przed spotkaniem przygotowali nawet startowy projekt. O ile Spockframework mialem okazje używać przy testowaniu aplikacji w Grails, zachwycony łatwością pisania testow, o tyle Roboelectric i buildy w Gradle byly dla mnie czyms zupelnie nowym.

Na poczatku mieliśmy trochę kłopotów z uruchomieniem projektu w IDE (Eclipse, Idea) ale wkrótce wiekszosci udało się to naprawić. W czasie sesji panowała zupełna dowolność. To para wybierała sobie temat - m.in. ćwiczenie TDD, nauka skrótów klawiszowych, kodowanie na kartce, ustalenie utrudnień (max 2 pola na klasę, max 4 linijki na metodę), testowanie widoków (Android View). W przerwie można było pograć w Quoridor.

Mnie udało się  w pierwszej sesji poćwiczyć TDD na zwykłym projekcie Javowym, potem powalczyłem z postawieniem projektu w Idei, następnie parę testów TDD w projekcie Androidowym.

Organizatorzy postawili nam również obiad, nie byle jaki ale składający się z pierwszego, drugiego dania i deseru :) Szacun dla nich.

Po obiedzie jeszcze parę sesji ale ogólny pęd do kodowania został trochę uśpiony (być może z powodu dobrego posiłku). W tej części poznałem bliżej roboguice i nauczyłem paru nowych skrótów klawiszowych w Idei. Dla szybszej nauki skrótów może być przydatny plugin Key Promoter  
(mousefeed to plugin dla Eclipse)
Niektóre przydatne skróty:

ctrl + j - wrzuć template kodu np. psvm rozwija domyślnie na public static void main (String[]args)...

ctrl + alt + N  - na metodzie zamienia wszystkie wywołania tego kodu ciałem metody i usuwa metodę
ctrl + alt + M - ekstrakt metody
ctrl + alt + V - ekstrakt zmiennej
ctrl + alt + F - ekstrakt pola
ctrl + alt + C - ekstrakt stałej
ctrl + alt + P - ekstrakt do paramertu metody

f2 - przenosi do najbliższego błędu kompilacji
alt + enter - autogenerate (metody lub przypisanie do zmiennej)
alt ~ - diff repo
ctrl + shift + 1 - podlinkowanie linii do 'ulubionych' pod pierwsza pozycja, analogicznie dla 2, 3..
ctrl +1 - skok do linku z ulubionych pod pierwszą pozycją
shift + f11 - wyświetlenie listy ulubionych
ctrl + q - wyświetla javadoc dla metody
ctrl + shift + f10 -  run projektu
shift + f9 - debug projektu
ctrl +  shift +strzałka góra/dół - przenoszenie linii kodu lub całej metody w dórę/dół pliku

Na koniec jedni się rozeszli a inni zostali jeszcze by kontynuować dyskusje przy browarze u Znajomych Znajomych ;)

A oto jak się skupiałem podczas jednej z sesji :D

środa, 2 stycznia 2013

Grails - klasa domenowa tylko do odczytu

Grails domyślnie nie wspiera oznaczenia klasy domenowej jako tylko do odczyty, tzn. tak żeby dynamiczne metody 'find' (find, get, list..) działały OK ale zapis, edycja encji nie była możliwa. Opcja taka jest szczególnie przydatna przy pracy z legacy bazami danych. Możemy jednak małym nakładem pracy zapewnić podobną funkcjonalność samemu. Udało mi się znaleźć przynajmniej 2 sposoby:

1. listenery beforeXXX w klasie domenowej np.:

class Demo {

    static constraints = {
    }
    String name

    transient beforeUpdate = {
        throw new RuntimeException('update not allowed')
    }
}

2. zwracanie kodu błędu z kontrolera dla niedozwolonych metod, np.:


    def delete(Long id) {
        response.sendError(405)
    }

Natomiast jeśli chcemy tylko wyłączyć z edycji w widoku wygenerowanym ze scaffoldingu jakieś pole klasy domenowe dostępna jest opcja w constrains:

class Demo {

    static constraints = {
         name(editable: false)
    }
    String name
}