【发布时间】:2014-05-26 02:26:13
【问题描述】:
我有两个模型,书签和标签。标签是通过acts-as-taggable-on gem 实现的,不过这里主要解释一下。
书签模型包含一个 url 字段。给定一个书签实例@bookmark,@bookmart.tags 返回它的标签。不同的书签可以共享同一个标签(即 Tag 中的 many 部分)。
标签有名字和taggings_count。 taggings_count 字段存储标签被标记到的书签数量。在幕后,有一个标签表,但这并不重要。
现在的问题是,我想检索所有由具有特定 url 值的书签标记的标签,结果应按标记某个标签的书签数量排序(该数量不一样作为 taggings_count 字段,它表示所有书签的标记计数,但需要此处为特定 url 的书签)。怎么做才能让生成的sql高效?
我知道我可以直接用sql写来提高效率,但我也想知道Rails是否可以在不损害太多性能的情况下做同样的事情,这样我就不必在我的Rails应用程序中注入sql代码
以下是表定义,在taggings表中,taggable_id作为Bookmark的外键,tag_id作为Tag的外键:
CREATE TABLE `bookmarks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`description` text,
`private` tinyint(1) DEFAULT NULL,
`read` tinyint(1) DEFAULT NULL,
`list_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `taggings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tag_id` int(11) DEFAULT NULL,
`taggable_id` int(11) DEFAULT NULL,
`taggable_type` varchar(255) DEFAULT NULL,
`tagger_id` int(11) DEFAULT NULL,
`tagger_type` varchar(255) DEFAULT NULL,
`context` varchar(128) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `taggings_idx` (`tag_id`,`taggable_id`,`taggable_type`,`context`,`tagger_id`,`tagger_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`taggings_count` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `index_tags_on_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
【问题讨论】:
-
如果你关心SQL查询的效率,你应该给我们:3张表的索引,“taggings”表的列。
-
另外,您使用的是哪个 Rails 版本?哪个数据库?
-
@tompave 检查我的表定义更新。我正在使用 Rails 4.1.0,它将部署到带有 mysql 的服务器
-
你在使用 Rails 的活动记录吗?或另一个数据库接口。看来您只需要您关心的书签的 id。 bookmark.where(url:your url).pluck(:id)[0] 如果只有一个。然后只需执行一个 tabable.where(id:) 并获取标签网址。
-
@bobbdelsol 是的,我正在使用活动记录。并且可能有多个具有相同 url 的书签。
标签: ruby-on-rails ruby acts-as-taggable-on