Homeland Ruby China on PostgreSQL

rivid · 2016年01月16日 · 最后由 tangmonk 回复于 2016年05月07日 · 11964 次阅读
本帖已被管理员设置为精华贴

RubyChina 是一个优秀的论坛,在中文 ruby 圈中有很大的影响力,许多 ruby 开发者都会学习他的代码,不过 RubyChina 已经是一个很复杂的系统,前后端有很多的模块,学习和部署使用都比较复杂,依赖的 mongoDB 和 ElasticSearch,都需要比较大的内存。

Goodbye MongoDB, Hello PostgreSQL mongoDB 是 Schemaless 的,很多实践显示 Schemaless 并没有那么好,使用 Schemaless 的存储,引入了隐形 schema 的问题。这些隐形的 schema 不是有存储引擎定义的,而是有应用程序定义的。像 mongoid 是在 model 中定义 schema,但是如果这样做,为什么不在数据库中定义呢?

在数据库中定义 schema 有一个好处,即重用性 (resuability),如果有多个应用要访问数据库,使用 Schemaless 将会造成混乱。

我的修改

我做了一个基于 postgreSQL 的移植 https://github.com/rivid/ruby-china/tree/postgresql

  1. 使用关系型数据库,保留传统的 schema。
  2. 利用 PostreSQL 9.4+ 的 regex,array 和 json 支持替换了 MongoDB。
  3. 利用 PostreSQL 的全文搜索的支持替换了 ElasticSearch。
  4. 前端体验保持不变。

存储和搜索都基于 PostgreSQL,使用熟悉的 ActiveRecord 减少了系统的复杂性,更易于维护。

其他基于我们系统的一些改动

Spec

spec 大部分已经测试通过,剩下 4 个没有通过,好像不影响实际使用。

1) TopicsHelper markdown should right with Chinese neer URL
   Failure/Error:
     expect(helper.markdown('此版本并非线上的http://yavaeye.com的源码.')).to eq(
       '<p>此版本并非线上的<a href="http://yavaeye.com" rel="nofollow" target="_blank">http://yavaeye.com</a>的源码.</p>'
     )

     expected: "<p>此版本并非线上的<a href=\"http://yavaeye.com\" rel=\"nofollow\" target=\"_blank\">http://yavaeye.com</a>的源码.</p>"
          got: "<p>此版本并非线上的http://yavaeye.com的源码.</p>"

     (compared using ==)
   # ./spec/helpers/topics_helper_spec.rb:8:in `block (3 levels) in <top (required)>'

2) sign up and login fail to sign up new user if password field is empty
   Failure/Error: expect(page).to have_content('密码不能为空字符')
     expected to find text "密码不能为空字符" in "Ruby China 社区Wiki招聘推文酷站 注册 登录 注册新用户 × 有 2 处问题导致无法提交: Password不能为空字符 Password confirmation与确认值不匹配 公开 Email / 登录"
   # ./spec/features/signup_login_spec.rb:39:in `block (2 levels) in <top (required)>'

3) sign up and login let user sign up and login to the site
   Failure/Error: expect(page).to have_content('社区精华帖')
     expected to find text "社区精华帖" in "Ruby China 社区Wiki招聘推文酷站 注册 登录 x没有该用户,请您重新注册。 登录 记住登录状态 注册 忘记了密码? 用其他平台的帐号登录 GitHub"
   # ./spec/features/signup_login_spec.rb:28:in `block (2 levels) in <top (required)>'

4) OAuth2 password get_token should work
   Failure/Error: @access_token = client.password.get_token(user.email, password)

   OAuth2::Error:
     invalid_grant: 授权方式无效,或者登录回调地址无效、过期或已被撤销
     {"error":"invalid_grant","error_description":"授权方式无效,或者登录回调地址无效、过期或已被撤销"}
   # ./spec/requests/oauth2_spec.rb:38:in `block (4 levels) in <top (required)>'
   # ./spec/requests/oauth2_spec.rb:37:in `block (3 levels) in <top (required)>'

项目地址

https://github.com/rivid/ruby-china/tree/postgresql

欢迎使用

很赞,已 star ! 👍

提交 Pull Request

本来我们也有打算从 Mongoid 换到 ActiveRecord 的

不过,实际上 MongoDb 没有那么多的内存需求,此外 Ruby China 这几年一直很稳定,没有一次数据库异常的问题

初略的翻阅了一下,发现几个问题

  1. Node 的 follow 功能被去掉了么?
  2. 我看到 Metion User 的那个测试被去掉了,后面又补回来么?
  3. 那些 Embedded Many 的表都处理好了么,比如关注

你不用发 PR 我来 cherry-pick 提取吧,或者如果要走 PR 的话,还需要修改好多东西,比如 upyun 的

#5 楼 @huacnlee

  1. Node 的 follow,我在网站上好像没找到按钮,只看到忽略节点,所以没有弄
  2. 我把 spec/models/mongoid/目录删除了,对应的代码变成 concern 了,认为其他地方会覆盖这部分逻辑的测试,如果没有覆盖的话,需要补上
  3. 关注用户,这些都处理了

@rivid 赞! 请问一下 schema 怎么搞出来的,手工做 migration? 还是写段代码从老的 mongoid model 里一个个 mode 抽所有 field name 和 mongoid type 再和 AR 的 sql type mapping 转换后 AR:Migration.new 再 create_table 并 add_column ?

#3 楼 @huacnlee 我正打算使用 mongoDB,请问出于什么考虑要换?

#7 楼 @huobazi 一个个 model 手工提取的,直接写到 schema.rb 中

@rivid 利用 PostreSQL 的全文搜索的支持替换 ElasticSearch 好赞,降低系统复杂度了。PostreSQL 的全文搜索对中文分词的支持好吗?

#10 楼 @psvr 分词是用 rmmseg-cpp 做的

赞一个

#3 楼 @huacnlee 请问为什么打算换呢。?

#4 楼 @huacnlee 不……实际上之前关联 GitHub 之后就有异常了。。。我搜不到自己的帖子了。。。

然而换到 pg 之后自己就好了。。。

#11 楼 @rivid

https://github.com/ruby-china/ruby-china/blob/master/app/controllers/search_controller.rb#L18

想学习下 rmmseg-cpp, 但是为啥我看到还是用的 elasticsearch 呢。。没有看到 rmmseg-cpp 的影子呢

#17 楼 @tangmonk

ruby-china 的搜索还是使用的 elasticsearch

请看我的 fork 中的 postgresql 分支,https://github.com/rivid/ruby-china/tree/postgresql

CLOSED: location can be nested in Nginx configure file


@rivid 请问 mina-puma 的 unix socket 如何配置 nginx 转发?我的配置

upstream app {
    # Path to Puma SOCK file, as defined previously
    server unix:/srv/foo/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name foo.com;

    location /api/ {
      try_files $uri @app;
    }

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

然而总是 404,文档没读明白

这个支持

以前是 mongodb?

yavaeye.com 被黑了

最近也在看 ruby china 的项目

赞一个 我也是看的 ruby-china 代码,写了一个 django+msyql 版本的

@huacnlee 我觉得你那个把 mongoid 的 id 改成数字的太坑爹了,再二次开发的时候如果从别的数据库导入一些数据就惨了。

#29 楼 @hlxwell 同样的方法调出自增 Id 就可以了呀

#30 楼 @huacnlee 就是要保持原来的 ID 才有了这个问题。哈哈。

@rivid 大大, 请问能不能讲解下 lib/search.rb 和 lib/postgres_search.rb 的原理啊

#32 楼 @tangmonk 最近都没有登录 http://rachbelaid.com/postgres-full-text-search-is-good-enough/ 看一下 postgres 全文搜索的原理和使用,search.rb 就是封装了下,使用了 RMMSeg 进行中文分词,没有使用 postgresql 自带的分词

huobazi 想知道 Ruby China 目前服务器配置情况 提及了此话题。 07月17日 21:59
需要 登录 后方可回复, 如果你还没有账号请 注册新账号