<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>smallfish logs &#187; MongoDB</title>
	<atom:link href="http://chenxiaoyu.org/blog/archives/tag/mongodb/feed" rel="self" type="application/rss+xml" />
	<link>http://chenxiaoyu.org</link>
	<description>关注 Python &#38; Go &#38; PostgreSQL</description>
	<lastBuildDate>Sat, 07 Aug 2010 10:31:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>[译] MongoDB 入门教程</title>
		<link>http://chenxiaoyu.org/blog/archives/242</link>
		<comments>http://chenxiaoyu.org/blog/archives/242#comments</comments>
		<pubDate>Tue, 27 Apr 2010 12:39:05 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[MongoDB]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=242</guid>
		<description><![CDATA[原文参见：http://www.mongodb.org/display/DOCS/Tutorial
启动数据库
下载 MongoDB, 解压后并启动:
$ bin/mongod
MongoDB 默认存储数据目录为 /data/db/ (或者 c:\data\db), 当然你也可以修改成不同目录, 只需要指定 &#8211;dbpath 参数:
$ bin/mongod --dbpath /path/to/my/data/dir
获取数据库连接
现在我们就可以使用自带的shell工具来操作数据库了. (我们也可以使用各种编程语言的驱动来使用MongoDB, 自带的shell工具可以方便我们管理数据库)
启动 MongoDB JavaScript 工具:
$ bin/mongo
默认 shell 连接的是本机localhost 上面的 test库, 会看到:
MongoDB shell version: 0.9.8
url: test
connecting to: test
type "help" for help
&#62;
&#8220;connecting to:&#8221; 这个会显示你正在使用的数据库的名称. 想换数据库的话可以:
&#62; use mydb
可以输入 help 来查看所有的命令.
插入数据到集合
下面我们来建立一个test的集合并写入一些数据. 建立两个对象, j 和 t , 并保存到集合中去.
在例子里  &#8216;&#62;&#8217;  来表示是 shell 输入提示符
&#62; j [...]]]></description>
			<content:encoded><![CDATA[<p>原文参见：<a href="http://www.mongodb.org/display/DOCS/Tutorial" target="_blank">http://www.mongodb.org/display/DOCS/Tutorial</a></p>
<p><strong>启动数据库</strong></p>
<p>下载 <a href="http://www.mongodb.org/display/DOCS/Downloads" target="_blank">MongoDB</a>, 解压后并启动:</p>
<pre>$ bin/mongod</pre>
<p>MongoDB 默认存储数据目录为 /data/db/ (或者 c:\data\db), 当然你也可以修改成不同目录, 只需要指定 &#8211;dbpath 参数:</p>
<pre>$ bin/mongod --dbpath /path/to/my/data/dir</pre>
<p><strong>获取数据库连接</strong></p>
<p>现在我们就可以使用自带的shell工具来操作数据库了. (我们也可以使用各种编程语言的驱动来使用MongoDB, 自带的shell工具可以方便我们管理数据库)</p>
<p>启动 MongoDB JavaScript 工具:</p>
<pre>$ bin/mongo</pre>
<p>默认 shell 连接的是本机localhost 上面的 test库, 会看到:</p>
<pre>MongoDB shell version: 0.9.8
url: test
connecting to: test
type "help" for help
&gt;</pre>
<p>&#8220;connecting to:&#8221; 这个会显示你正在使用的数据库的名称. 想换数据库的话可以:</p>
<pre>&gt; use mydb</pre>
<p>可以输入 help 来查看所有的命令.</p>
<p><strong>插入数据到集合</strong></p>
<p>下面我们来建立一个test的集合并写入一些数据. 建立两个对象, j 和 t , 并保存到集合中去.<br />
在例子里  &#8216;&gt;&#8217;  来表示是 shell 输入提示符</p>
<pre>&gt; j = { name : "mongo" };
{"name" : "mongo"}
&gt; t = { x : 3 };
{ "x" : 3  }
&gt; db.things.save(j);
&gt; db.things.save(t);
&gt; db.things.find();
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
{"x" : 3 , "_id" : ObjectId("497cf61651712cf7758fbdbc")}
&gt;</pre>
<p>有几点需要注意下 :</p>
<ul>
<li>不需要预先建立一个集合. 在第一次插入数据时候会自动建立.</li>
<li>在例子其实可以存储任何结构的数据, 当然在实际应用我们存储的还是相同元素的集合. 这个特性其实可以在应用里很灵活, 你不需要类似 alter table 来修改你的数据结构</li>
<li>每次插入数据时候对象都会有一个ID, 名字叫 _id.</li>
</ul>
<p>当你运行不同的例子, 你的对象ID值都是不同的.</p>
<p>下面再加点数据:</p>
<pre>&gt; for( var i = 1; i &lt; 10; i++ ) db.things.save( { x:4, j:i } ); &gt; db.things.find();
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
{"x" : 3 , "_id" : ObjectId("497cf61651712cf7758fbdbc")}
{"x" : 4 , "j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
{"x" : 4 , "j" : 2 , "_id" : ObjectId("497cf87151712cf7758fbdbe")}
{"x" : 4 , "j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}
{"x" : 4 , "j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}
{"x" : 4 , "j" : 5 , "_id" : ObjectId("497cf87151712cf7758fbdc1")}
{"x" : 4 , "j" : 6 , "_id" : ObjectId("497cf87151712cf7758fbdc2")}
{"x" : 4 , "j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"x" : 4 , "j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}</pre>
<p>请注意下, 这里循环次数是10, 但是只显示到8, 还有2条数据没有显示.</p>
<p>如果想继续查询下面的数据只需要使用 it 命令, 就会继续下面的数据:</p>
<pre>{"x" : 4 , "j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"x" : 4 , "j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}</pre>
<p>继续</p>
<pre>&gt; it
{"x" : 4 , "j" : 9 , "_id" : ObjectId("497cf87151712cf7758fbdc5")}
{"x" : 4 , "j" : 10 , "_id" : ObjectId("497cf87151712cf7758fbdc6")}</pre>
<p>从技术上讲 find() 返回一个游标对象. 但在上面的例子里, 并没有拿到一个游标的变量. 所以 shell 自动遍历游标, 返回一个初始化的set, 并允许我们继续用 it 迭代输出.</p>
<p>当然我们也可以直接用游标来输出, 不过这个是下一部分的内容了.</p>
<p><strong>查询数据</strong></p>
<p>在没有深入查询之前, 我们先看看怎么从一个查询中返回一个游标对象. 可以简单的通过 find() 来查询, 他返回一个任意结构的集合. 如果实现特定的查询稍后讲解.</p>
<p>实现上面同样的查询, 然后通过 while 来输出:</p>
<pre>&gt; var cursor = db.things.find();
&gt; while (cursor.hasNext()) { print(tojson(cursor.next())); }
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
{"x" : 3 , "_id" : ObjectId("497cf61651712cf7758fbdbc")}
{"x" : 4 , "j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
{"x" : 4 , "j" : 2 , "_id" : ObjectId("497cf87151712cf7758fbdbe")}
{"x" : 4 , "j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}
{"x" : 4 , "j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}
{"x" : 4 , "j" : 5 , "_id" : ObjectId("497cf87151712cf7758fbdc1")}
{"x" : 4 , "j" : 6 , "_id" : ObjectId("497cf87151712cf7758fbdc2")}
{"x" : 4 , "j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"x" : 4 , "j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}
{"x" : 4 , "j" : 9 , "_id" : ObjectId("497cf87151712cf7758fbdc5")}
&gt;</pre>
<p>上面的例子显示了游标风格的迭代输出. hasNext() 函数告诉我们是否还有数据, 如果有则可以调用 next() 函数. 这里我们也用了自带的 tojson() 方法返回一个标准的 JSON 格式数据.</p>
<p>当我们使用的是 JavaScript shell, 可以用到JS的特性, forEach 就可以输出游标了. 下面的例子就是使用 forEach() 来循环输出:</p>
<pre>&gt; db.things.find().forEach( function(x) { print(tojson(x));});
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
{"x" : 3 , "_id" : ObjectId("497cf61651712cf7758fbdbc")}
{"x" : 4 , "j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
{"x" : 4 , "j" : 2 , "_id" : ObjectId("497cf87151712cf7758fbdbe")}
{"x" : 4 , "j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}
{"x" : 4 , "j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}
{"x" : 4 , "j" : 5 , "_id" : ObjectId("497cf87151712cf7758fbdc1")}
{"x" : 4 , "j" : 6 , "_id" : ObjectId("497cf87151712cf7758fbdc2")}
{"x" : 4 , "j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"x" : 4 , "j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}
{"x" : 4 , "j" : 9 , "_id" : ObjectId("497cf87151712cf7758fbdc5")}
&gt;</pre>
<p>forEach() 必须定义一个函数供每个游标元素调用.</p>
<p>在 mongo shell 里, 我们也可以把游标当作数组来用 :</p>
<pre>&gt; var cursor = db.things.find();
&gt; print (tojson(cursor[4]));
{"x" : 4 , "j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}</pre>
<p>使用游标时候请注意占用内存的问题, 特别是很大的游标对象, 有可能会内存溢出. 所以应该用迭代的方式来输出.</p>
<p>下面的示例则是把游标转换成真实的数组类型:</p>
<pre>&gt; var arr = db.things.find().toArray();
&gt; arr[5];
{"x" : 4 , "j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}</pre>
<p>请注意这些特性只是在 mongo shell 里使用, 而不是所有的其他应用程序驱动都支持.</p>
<p>MongoDB 游标对象不是没有快照 &#8211; 如果有其他用户在集合里第一次或者最后一次调用 next(), 你可以得不到游标里的数据. 所以要明确的锁定你要查询的游标.</p>
<p><strong>指定条件的查询</strong></p>
<p>到这里我们已经知道怎么从游标里实现一个查询并返回数据对象, 下面就来看看怎么根据指定的条件来查询.</p>
<p>下面的示例就是说明如何执行一个类似SQL的查询, 并演示了怎么在 MongoDB 里实现. 这是在 MongoDB shell 里查询, 当然你也可以用其他的应用驱动或者语言来实现:</p>
<pre>SELECT * FROM things WHERE name="mongo"</pre>
<pre>&gt; db.things.find({name:"mongo"}).forEach(function(x) { print(tojson(x));});
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
&gt;</pre>
<pre>SELECT * FROM things WHERE x=4</pre>
<pre>&gt; db.things.find({x:4}).forEach(function(x) { print(tojson(x));});
{"x" : 4 , "j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
{"x" : 4 , "j" : 2 , "_id" : ObjectId("497cf87151712cf7758fbdbe")}
{"x" : 4 , "j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}
{"x" : 4 , "j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}
{"x" : 4 , "j" : 5 , "_id" : ObjectId("497cf87151712cf7758fbdc1")}
{"x" : 4 , "j" : 6 , "_id" : ObjectId("497cf87151712cf7758fbdc2")}
{"x" : 4 , "j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"x" : 4 , "j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}
{"x" : 4 , "j" : 9 , "_id" : ObjectId("497cf87151712cf7758fbdc5")}
&gt;</pre>
<p>查询条件是 { a:A, b:B, &#8230; } 类似 &#8220;where a==A and b==B and &#8230;&#8221;, 更多的查询方式可以参考 Mongo 开发教程部分.</p>
<p>上面显示的是所有的元素, 当然我们也可以返回特定的元素, 类似于返回表里某字段的值, 只需要在 find({x:4}) 里指定元素的名字, 比如 j:</p>
<pre>SELECT j FROM things WHERE x=4</pre>
<pre>&gt; db.things.find({x:4}, {j:true}).forEach(function(x) { print(tojson(x));});
{"j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
{"j" : 2 , "_id" : ObjectId("497cf87151712cf7758fbdbe")}
{"j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}
{"j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}
{"j" : 5 , "_id" : ObjectId("497cf87151712cf7758fbdc1")}
{"j" : 6 , "_id" : ObjectId("497cf87151712cf7758fbdc2")}
{"j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}
{"j" : 9 , "_id" : ObjectId("497cf87151712cf7758fbdc5")}
&gt;</pre>
<p>请注意 &#8220;_id&#8221; 元素会一直被返回.</p>
<p><strong>findOne() &#8211; 语法糖</strong></p>
<p>为了方便, mongo shell (其他驱动) 避免游标的可能带来的开销, 提供一个findOne() 函数. 这个函数和 find() 参数一样, 不过他返回游标里第一条数据, 或者返回 null 空数据库.</p>
<p>作为一个例子, name==&#8217;mongo&#8217; 可以用很多方法来实现, 可以用 next() 来循环游标(需要校验是否为null), 或者当做数组返回第一个元素.</p>
<p>但是用 findOne() 方法则更简单和高效:</p>
<pre>&gt; var mongo = db.things.findOne({name:"mongo"});
&gt; print(tojson(mongo));
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
&gt;</pre>
<p>findOne 方法更跟 find({name:&#8221;mongo&#8221;}).limit(1) 一样.</p>
<p><strong>limit() 查询</strong></p>
<p>你可以需要限制结果集的长度, 可以调用 limit 方法.</p>
<p>这是强烈推荐高性能的原因, 通过限制条数来减少网络传输, 例如:</p>
<pre>&gt; db.things.find().limit(3);
in cursor for : DBQuery: example.things -&gt;
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
{"x" : 3 , "_id" : ObjectId("497cf61651712cf7758fbdbc")}
{"x" : 4 , "j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
&gt;</pre>
<p><strong>更多帮助</strong></p>
<p>除非了一般的 help 之外, 你还可以查询 help 数据库和db.whatever 来查询具体的说明.</p>
<p>如果你对一个函数要做什么, 你可以不输入 {{()}} 这些结束的括号则可以输出实现的源码, 例如:</p>
<pre>&gt; db.foo.insert
function (obj, _allow_dot) {
    if (!obj) {
        throw "no object passed to insert!";
    }
    if (!_allow_dot) {
        this._validateForStorage(obj);
    }
    return this._mongo.insert(this._fullName, obj);
}</pre>
<p>mongo 是一个完整的 JavaScript shell程序, 所以在 shell 里完全可以私用JS的方法、类、语法. 此外, MongoDB 定义很多自己的类和全局变量 (比如 db). 这里可以查看完整的API说明 <a href="http://api.mongodb.org/js/" target="_blank">http://api.mongodb.org/js/</a>.</p>
<p><strong>接下来</strong></p>
<p>看完这篇教程后下一步则看MongoDB更详细的文档 <a href="http://www.mongodb.org/display/DOCS/Manual" target="_blank">http://www.mongodb.org/display/DOCS/Manual</a></p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2010. |
<a href="http://chenxiaoyu.org/blog/archives/242">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/242#comments">8 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/242&title=[译] MongoDB 入门教程">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/mongodb" rel="tag">MongoDB</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/242/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Python(Stackless) + MongoDB Apache 日志(2G)分析</title>
		<link>http://chenxiaoyu.org/blog/archives/213</link>
		<comments>http://chenxiaoyu.org/blog/archives/213#comments</comments>
		<pubDate>Thu, 04 Mar 2010 01:49:34 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=213</guid>
		<description><![CDATA[为何选择Stackless？ http://www.stackless.com
Stackless可以简单的认为是Python一个增强版，最吸引眼球的非“微线程”莫属。微线程是轻量级的线程，与线程相比切换消耗的资源更小，线程内共享数据更加便捷。相比多线程代码更加简洁和可读。此项目是由EVE Online推出，在并发和性能上确实很强劲。安装和Python一样，可以考虑替换原系统Python。:)
为何选择MongoDB？ http://www.mongodb.org
可以在官网看到很多流行的应用采用MongoDB，比如sourceforge，github等。相比RDBMS有啥优势？首先在速度和性能上优势最为明显，不仅可以当作类似KeyValue数据库来使，还包含了一些数据库查询（Distinct、Group、随机、索引等特性）。再有一点特性就是：简单。不论是应用还是文档，还是第三方API，几乎略过一下就可以使用。不过有点遗憾的就是，存储的数据文件很大，超过正常数据的2-4倍之间。本文测试的Apache日志大小是2G，生产的数据文件有6G。寒&#8230;希望在新版里能有所缩身，当然这个也是明显的以空间换速度的后果。
本文除去上面提及到的两个软件，还需要安装pymongo模块。http://api.mongodb.org/python/
模块安装方式有源码编译和easy_install，这里就不再累赘。
1. 从Apache日志中分析出需要保存的资料，比如IP，时间，GET/POST，返回状态码等。
fmt_str  = '(?P&#60;ip&#62;[.\d]+) - - \[(?P&#60;time&#62;.*?)\] "(?P&#60;method&#62;.*?) (?P&#60;uri&#62;.*?) HTTP/1.\d" (?P&#60;status&#62;\d+) (?P&#60;length&#62;.*?) "(?P&#60;referere&#62;.*?)" "(?P&#60;agent&#62;.*?)"'
fmt_name = re.findall('\?P&#60;(.*?)&#62;', fmt_str)
fmt_re   = re.compile(fmt_str)
定义了一个正则用于提取每行日志的内容。fmt_name就是提取尖括号中间的变量名。
2. 定义MongoDB相关变量，包括需要存到collection名称。Connection采取的是默认Host和端口。
conn     = Connection()
apache   = conn.apache
logs     = apache.logs
3. 保存日志行
def make_line(line):
    m = fmt_re.search(line)
    if m:
 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>为何选择Stackless？</strong> <a href="http://www.stackless.com" target="_blank">http://www.stackless.com</a></p>
<p>Stackless可以简单的认为是Python一个增强版，最吸引眼球的非“微线程”莫属。微线程是轻量级的线程，与线程相比切换消耗的资源更小，线程内共享数据更加便捷。相比多线程代码更加简洁和可读。此项目是由EVE Online推出，在并发和性能上确实很强劲。安装和Python一样，可以考虑替换原系统Python。:)</p>
<p><strong>为何选择MongoDB？</strong> <a href="http://www.mongodb.org" target="_blank">http://www.mongodb.org</a></p>
<p>可以在官网看到很多流行的应用采用MongoDB，比如sourceforge，github等。相比RDBMS有啥优势？首先在速度和性能上优势最为明显，不仅可以当作类似KeyValue数据库来使，还包含了一些数据库查询（Distinct、Group、随机、索引等特性）。再有一点特性就是：简单。不论是应用还是文档，还是第三方API，几乎略过一下就可以使用。不过有点遗憾的就是，存储的数据文件很大，超过正常数据的2-4倍之间。本文测试的Apache日志大小是2G，生产的数据文件有6G。寒&#8230;希望在新版里能有所缩身，当然这个也是明显的以空间换速度的后果。</p>
<p>本文除去上面提及到的两个软件，还需要安装pymongo模块。<a href="http://api.mongodb.org/python/" target="_blank">http://api.mongodb.org/python/</a></p>
<p>模块安装方式有源码编译和easy_install，这里就不再累赘。</p>
<p>1. 从Apache日志中分析出需要保存的资料，比如IP，时间，GET/POST，返回状态码等。</p>
<pre>fmt_str  = '(?P&lt;ip&gt;[.\d]+) - - \[(?P&lt;time&gt;.*?)\] "(?P&lt;method&gt;.*?) (?P&lt;uri&gt;.*?) HTTP/1.\d" (?P&lt;status&gt;\d+) (?P&lt;length&gt;.*?) "(?P&lt;referere&gt;.*?)" "(?P&lt;agent&gt;.*?)"'
fmt_name = re.findall('\?P&lt;(.*?)&gt;', fmt_str)
fmt_re   = re.compile(fmt_str)</pre>
<p>定义了一个正则用于提取每行日志的内容。fmt_name就是提取尖括号中间的变量名。</p>
<p>2. 定义MongoDB相关变量，包括需要存到collection名称。Connection采取的是默认Host和端口。</p>
<pre>conn     = Connection()
apache   = conn.apache
logs     = apache.logs</pre>
<p>3. 保存日志行</p>
<pre>def make_line(line):
    m = fmt_re.search(line)
    if m:
        logs.insert(dict(zip(fmt_name, m.groups())))</pre>
<p>4. 读取Apache日志文件</p>
<pre>def make_log(log_path):
    with open(log_path) as fp:
        for line in fp:
            make_line(line.strip())</pre>
<p>5. 运行把。</p>
<pre>if __name__ == '__main__':
    make_log('d:/apachelog.txt')</pre>
<p>脚本大致情况如此，这里没有放上stackless部分代码，可以参考下面代码：</p>
<pre>import stackless
def print_x(x):
    print x
stackless.tasklet(print_x)('one')
stackless.tasklet(print_x)('two')
stackless.run()</pre>
<p>tasklet操作只是把类似操作放入队列中，run才是真正的运行。这里主要用于替换原有多线程threading并行分析多个日志的行为。</p>
<p><strong>补充：</strong></p>
<p>Apache日志大小是2G，671万行左右。生成的数据库有6G。</p>
<p>硬件：Intel(R) Core(TM)2 Duo CPU E7500 @ 2.93GHz 台式机</p>
<p>系统：RHEL 5.2 文件系统ext3</p>
<p>其他：Stackless 2.6.4 MongoDB 1.2</p>
<p>在保存300万左右时候，一切正常。不管是CPU还是内存，以及插入速度都很不错，大概有8-9000条/秒。和以前笔记本上测试结果基本一致。再往以后，内存消耗有点飙升，插入速度也降低。500万左右记录时候CPU达到40%，内存消耗2.1G。在生成第二个2G数据文件时候似乎速度和效率又提升上去了。最终保存的结果不是太满意。</p>
<p>后加用笔记本重新测试了一下1000万数据，速度比上面的671万明显提升很多。初步怀疑有两个地方可能会影响性能和速度：</p>
<p>1. 文件系统的差异。笔记本是Ubuntu 9.10，ext4系统。搜了下ext3和ext4在大文件读写上会有所差距。</p>
<p>2. 正则匹配上。单行操作都是匹配提取。大文件上应该还有优化的空间。</p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2010. |
<a href="http://chenxiaoyu.org/blog/archives/213">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/213#comments">6 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/213&title=Python(Stackless) + MongoDB Apache 日志(2G)分析">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/mongodb" rel="tag">MongoDB</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/python" rel="tag">Python</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/213/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
