2012年1月18日 星期三

[mongodb]mongo database 芒果資料庫-開端

Mongo database 是資料庫的一種。
屬於 NoSQL 的這一種。
從學校學資料庫的時候,還有碰過不是關聯式資料庫的嗎?

在近年來,資料庫的應用環境變化,
讓所謂 NoSQL 的資料庫大顯身手,
這些資料庫聲稱更能適應網路應用,更能適應資料變化,更能適應分散管理,
而芒果資料庫,就是其中之一。

它採用所謂的 document-oriented,讓它的每筆資料(也就是一個 document,也有人按舊習慣叫 record),
都是個 dictionary 物件,可以任意加屬性(或按舊習慣稱做 field),
一群你認為同類的 document,就裝在一個 collection 裡面。
對於用過 javascript 的人都知道,dictionary 跟 class 是一體的兩面,
只要拿得到 dictionary 的序列化表示,javascript 就等於拿到一個物件,
在網頁上的應用當然超方便,server side 或 client 的程式就不用想如何從 table 轉換成物件。
靈活的 field 增減,也不用太過擔心 schema 的變化,
field 的值也不只限單一值,也可以是個 list,或是個 dictionary,可像個樹一樣的結構長大,
面對一個人有三個電話號碼的這種資料,是輕鬆自然又直覺,不用像以前一樣用分隔符號分開,
然後限制哪些符號不行在值裡面出現之類的地雷。

當然開頭一定是因為宣傳廣告吸引了我,才會開始想要用他。
http://www.mongodb.org
既然有想,就開始試用吧,不用不會知道優缺點的。
如果你也有類似的需求,你可以試試。

類似的資料庫還有 Apache 的 Cassandra ,
http://www.datastax.com/docs/0.8/introduction/index#getting-started-with-cassandra

2011年12月28日 星期三

[python]dict sort by key or value

熊熊忘記該怎麼 sort by value,查了一下網路記下來。

for key in sorted(mydict.iterkeys()):
print "%s: %s" % (key, mydict[key])

 

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
print "%s: %s" % (key, value)

 



# (IMHO) the simplest approach:
def sortedDictValues1(adict):
items = adict.items()
items.sort()
return [value for key, value in items]

# an alternative implementation, which
# happens to run a bit faster for large
# dictionaries on my machine:
def sortedDictValues2(adict):
keys = adict.keys()
keys.sort()
return [dict[key] for key in keys]

# a further slight speed-up on my box
# is to map a bound-method:
def sortedDictValues3(adict):
keys = adict.keys()
keys.sort()
return map(adict.get, keys)

 



d= [ {'id':0, 'value':9}, {'id':1, 'value':100}, {'id':5, 'value':99}, {'id':3, 'value':19}, {'id':2, 'value':59} ]
d.sort(key=lambda x:x['id']) #針對key 'id' 做sort
d.sort(key=lambda x:x['value']) #針對key 'value' 做sort

#以下用cmp,可以達到上面指定key的效果
d.sort(cmp=lambda x,y: cmp(x['id'], y['id']))
d.sort(cmp=lambda x,y: cmp(x['value'], y['value']))

 

class data:
def __init__(self, _id, _value):
self.id = _id
self.value = _value
c = [ data(0,9), data(1,100), data(5,99), data(3,19), data(2,59) ]
c.sort(key=lambda x:x.id)#針對class member id 做sort
c.sort(key=lambda x:x.value)#針對class member value 做sort

#以下用cmp,可以達到上面指定key的效果
c.sort(cmp=lambda x,y: cmp(x.id, y.id) )
c.sort(cmp=lambda x,y: cmp(x.value, y.value))

2011年12月23日 星期五

[python]datetime

從 javascript 的 datetime 的 timestamp 了解到,
python 無法直接獲得 timestamp 的值。
一般來說這個 timestamp 指的是Unix epoch (or Unix time or POSIX time or Unix timestamp)
根據這裡提到,也許是 datetime 的表示法有很多種,且精準度高於 timestamp,
所以就沒有直接提供方法。

但是也不是沒辦法。

在得到一個 datetime object 後

import datetime
x = datetime.datetime.now()

# datetime.datetime(2011, 12, 23, 17, 17, 58, 625000)

第一種是藉 calendar 模組

>>> import calendar
>>> calendar.timegm(x.timetuple())
1324660678

這是得到標準時區的 timestamp,所以要轉回原來時區(local)的時間,不能用 fromtimestamp,
而是要用 utcfromtimestamp

>>> y = calendar.timegm(x.timetuple())
>>> z = datetime.datetime.fromtimestamp(y)
>>> z
datetime.datetime(2011, 12, 24, 1, 17, 58)
>>> y = calendar.timegm(x.timetuple())
>>> z = datetime.datetime.utcfromtimestamp(y)
>>> z
datetime.datetime(2011, 12, 23, 17, 17, 58)

另一個方法是用 time 模組,產生出來的 timestamp 就長不一樣。
這個用 fromtimestamp 就可以得到local datetime。

>>> import time
>>> y = time.mktime(x.timetuple())
>>> y
1324631878.0
>>> z = datetime.datetime.fromtimestamp(y)
>>> z
datetime.datetime(2011, 12, 23, 17, 17, 58)

這裡有個貼心的網站,幫你整理各語言如何得到 timestamp。
http://www.epochconverter.com/

在寫程式時一定要先測試一下數值是否如你所想喔

[javascript]時間的操作

時間物件的實體化有四種

var dt = new Date();
var dt = new Date(milliseconds);
var dt = new Date(dateString);
var dt = new Date(year, month, day, hours, minutes, seconds, milliseconds);

如果是要現在時間,就用第一個即可。

第二種方法的 milliseconds 是從 1970/01/01 開始算。
這個數字通常不會是自己算,而是從別的地方傳來。
他的好處是,用一個 float 就可以表示一個時間,比字串更省空間。
同時排序、計算(時間加減)也更快速。
在 .Net 裡,所謂的 timestamp 就是這個數值;
python 裡,據說有些轉換上的問題, 也就沒有提供 datetime 直接產生 timestamp 的方法。
這裡先不提。
javascript 則是有 getTime() 方法可以產生這個數字。
但是要注意時區問題,不然會有時間差喔。

第三種方法的 dateString 就要看運氣了,格式還是要對 javascript 的胃口。
如果沒把握,以下格式是可以的:
"October 13, 1975 11:13:00"
"12-23 13:44:32, 2011"
"Dec 23 14:00:12 2011"
而我最愛的格式不行:
"2011-12-23 13:44:32"

第四種方法就穩定,每一項分開就不會有問題。

全部要注意的是千禧年問題,也就是以前常把四位數年份表示縮成兩位數,
請記得不要再這樣做了,這不是一個好習慣。

2011年11月23日 星期三

[dotnet]webbrowser 做為 UI log 的眉眉角角

一開始的動作

'WebBrowser1 一開始,可以設定 DocumentText 來顯示第一個畫面。
若是想用,WebBrowser1.Document.Write,
因為一開始,WebBrowser1.Document 是 nothing,所以此路不通。
網路上也滿多人提出,先 WebBrowser1.Navigate("about:blank"),
然後用迴圈加上 Application.DoEvents() 等待 'WebBrowser1.Document 長好,
再用 WebBrowser1.Document.Write。

最後我的決定是,準備好一個檔案直讀進來就好。
因為程式是 multithread,保險起見,還是用 while 等 Document 長好。
但我不確定是否真有用,因為一定要用 Application.DoEvents() 讓 WebBrowser 去做事,
當然這時有其他事情發生也沒辦法阻止。

    Sub initUILogComponet()
        WebBrowser1.Navigate("UI.html")
        WebBrowser1.IsWebBrowserContextMenuEnabled = False
        While (True)
            Application.DoEvents()
            If Not WebBrowser1.Document.Body Is Nothing Then
                Exit While
            End If
        End While
    End Sub

更新畫面

要更新 UI 畫面,基本要做的就是檢查 thread 是否回到 form。
這裡用 Document 物件新增新的 tr。
等待之後,取出 Document 的 html 元素的 OuterHtml 再寫進檔案。
接著Navigate。
清除舊資料的方式就是把最舊的那一個元素的 OuterHtml 取出,
把它從 html 元素的 OuterHtml 裡消掉,
再寫進檔案後Navigate。

    Sub UpdateUILog(ByVal inType As EQS_ScreenType, ByVal intxt As String)
        If Me.InvokeRequired Then
            Me.Invoke(New LogDele(AddressOf UpdateUILog), New Object() {inType, intxt})
        Else
            Try
                Dim tr As HtmlElement
                Dim td As HtmlElement
                tr = WebBrowser1.Document.CreateElement("tr")
                td = WebBrowser1.Document.CreateElement("td")
                td.InnerText = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
                tr.AppendChild(td)
                td = WebBrowser1.Document.CreateElement("td")
                td.InnerText = intxt
                tr.AppendChild(td)
                Select Case inType
                    Case ERROR
                        tr.SetAttribute("class", "error")
                    Case M_INFO
                        tr.SetAttribute("class", "info")
                    Case M_MES
                End Select
                WebBrowser1.Document.Body.FirstChild.FirstChild.FirstChild.InsertAdjacentElement(HtmlElementInsertionOrientation.AfterEnd, tr)
                While (True)
                    Application.DoEvents()
                    If Not WebBrowser1.Document.Body Is Nothing Then
                        Exit While
                    End If
                End While
                Dim n_html = "<!doctype html>" & WebBrowser1.Document.GetElementsByTagName("html").Item(0).OuterHtml
                Dim n_sw As System.IO.StreamWriter = System.IO.File.CreateText("UI.html")
                n_sw.Write(n_html)
                n_sw.Close()
                WebBrowser1.Navigate("UI.html")
                Dim v As Integer
                v = 5
                If WebBrowser1.Document.Body.FirstChild.FirstChild.Children.Count > v Then
                    Dim t As String = WebBrowser1.Document.Body.FirstChild.FirstChild.Children(v).OuterHtml
                    Dim new_html As String = WebBrowser1.Document.GetElementsByTagName("html").Item(0).OuterHtml
                    t = t.Replace(vbNewLine, "")
                    new_html = new_html.Replace(vbNewLine, "")
                    new_html = new_html.Replace(t, "")
                    new_html = "<!doctype html>" & new_html

                    Dim sw As System.IO.StreamWriter = System.IO.File.CreateText("UI.html")
                    sw.Write(new_html)
                    sw.Close()
                    WebBrowser1.Navigate("UI.html")
                End If
            Catch ex As Exception

            End Try
        End If
    End Sub

 

保證一定得到更新後內容的方式

在 DocumentCompleted 事件去拿一定可以。
要注意的是,當初設定 DocumentText 的話,更新的內容會在 DocumentText。
而使用 Document 物件操作的,更新的內容要從 Document 物件拿。

    Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
        If firstContextSetComplete = False Then
            firstContextSetComplete = True
            'UpdateUILog(FACETEA.EQS_ScreenType.M_INFO, "StartUp")
        End If
        Dim control As Control = Me.ActiveControl
        WebBrowser1.Focus()
        control.Focus()
    End Sub

用jQuery清除舊資料

因為 WebBrowser 控制項沒辦法支援 addEventHandler,所以我的腦筋動到 setInterval。
這個方法可行,但是無法存檔。
而且考量到使用 class 控制外觀非得存檔再Navigate,在兩個因素考量下,
所以清舊資料的事只能交給主程式本身來做。

[dotnet]WebBrowser控制項對於 tr 的 border 顯示

在WebBrowser控制項裡,

tr { border-bottom: 1px solid #000000;}

不會顯示線。

在 ie9 的話,上面那行再加

table { border-collapse:collapse;}

就會顯示線。

有人提到

tr td{ border-bottom: 1px solid #000000; }

可以解決問題。但是兩個 td 之間可能會有斷線。

[dotnet]WebBrowser控制項不可用script偵測新增節點

經過研究及試驗,在 ie9 以下這行可以成功

document.addEventListener("DOMNodeInserted",function(){alert('change')});

但是在WebBrowser控制項就失敗。