MongoDB中动态标签的策略

时间:2012-04-22 00:11:44

标签: design-patterns mongodb tags

在Facebook状态上,您可以开始键入@并标记处于状态的用户。这个问题不是关于前端,而是如何存储该功能的数据。以通用方式实现此功能的最佳方式是以动态方式表示字符串中的任何mongodb实体。目标是如果实体改变,它在存储的字符串中的表示也会改变。例如,我有一个想法是:

Post: {
    _id: "48ajsdlfhsdjfkjsljsd"
    name: "Post One",
    text: "@user is the best for liking @thing, and @thing"
    tags: [user:1234, thing:456, thing:789]
}

所以我会加载这篇文章,然后查看标签,为每个标签类型和id加载模型,然后将字符串重写为:“Chris最喜欢StackOverflow和Mongo”。这似乎效率低下,有任何更好的想法吗?

2 个答案:

答案 0 :(得分:1)

你的回答适用于Geoff,但我一直在寻找更高效的东西。我所做的是将文档存储在Mongo中,就像这样

{
    _id: "4bdslakjghjdgkjsh123",
    title: "Post One",
    text: "@ is cool for liking @",
    tags: ["user:4bcasdkasd89", "product:4basfkjafkjlfl"]
}

转换标记的代码在加载消息后运行。它基本上使用标签来知道要使用哪种类型的模型,以及加载它的id。然后,它使用模型的as_tag方法或to_s创建一个值数组。然后将此数组替换为原始字符串,以替换@符号。很像sprintf。所以它转化为“克里斯喜欢骑自行车很酷”

def after_initialize
    tags = self.collect_tags
    tags.each do |value|
      self.text.sub!(/@/, value)
    end
end

def collect_tags
    self.tags.collect do |tag|
        model, id = tag.split(':')
        model[0] = model[0,1].upcase
        m = Models.const_get(model).find(id)
        if(m.respond_to? 'as_tag')
            m.as_tag
        else
            m.to_s
        end
    end
end

有什么方法可以提高效率吗?

答案 1 :(得分:0)

虽然不太确定你要做什么,但我建议如下:

  1. 创建一个文档,作为字符串中“@”标记与MongoDB文档中字段之间的映射。

  2. 修改Post文档,以便tags数组包含标准化文档,这些文档既标识存储实际数据的文档的_id值,又标识应在这些文档中采集数据的字段。

  3. (可选)修改Post文档,以显式包含映射文档_id。如果有全局映射文档,则这是不必要的,但

  4. 在您的示例中,映射文档可能如下所示:

    Mapping: { _id: "abc..", maps: [{tag:"user", field:"user.person.nickname"}, {tag:"thing", field:"object.name"}] }
    

    帖子文件看起来像:

    Post: { _id: "48ajsdlfhsdjfkjsljsd",
      name: "Post One",
      text: "@user is the best for liking @thing, and @thing",
      tags: [{tag:"user", docId:"pqr..."}, {tag:"thing", docId:"xzy..."}, {tag:"thing", docId:"mno..."}],
      mapping: "abc..."
    }
    

    然后,您需要执行以下操作以返回文本字符串:

    1. 加载帖子文档
    2. 提取并加载Mapping文档(如果此映射是全局的,则不需要此步骤)
    3. 在一次加载中加载与基础数据相对应的所有文档:

      db.posts.find({_ id:{$ in:[“pqr ...”,“xyz ...”,“mno ...”]}})

    4. 从每个找到的文档

    5. 中检索所需文档字段中的值
    6. 将代码替换为字段值
    7. 这种方法允许您更改字符串中标记的含义(通过更改Mapping文档 - 例如,您可以将@user从nickname更改为realname),以及标记的值(通过更改存储的docIds)在Post文档中的标签列表中),但字符串生成仍然至少有4个步骤。

      该方法不处理Mapping文档不包含标记的条件,或者标记列表与文本字符串中的标记数量不同的情况。