Groovy:以 Maps 作为键的 MultiValueMap

发布于 2024-11-30 07:12:11 字数 983 浏览 3 评论 0原文

这是我正在考虑做的事情,我想知道你是否认为这是一个好主意。

我从数据库中检索了一堆行,在 groovy 中它给了我一个列表列表,类似于:

[
  [ 'Dog', 'M', 'Mutt', 'Sammy' ],
  [ 'Cat', 'F', 'Siamese', 'Pat' ],
  [ 'Dog', 'M', 'Husky', 'Taco' ],
  ...
]

不是我真正的数据集,但你明白了。

由于我会非常频繁地提取这些数据,并在将其呈现在 UI 中之前对其进行一些分析,因此我想将其存储在 MultiValueMap 由 groovy 映射(即 LinkedHashMaps)键控,因此我可以检索我需要的部分内容,而无需访问每次都到数据库。它是来自多个表的数据子集的缓存(比上面的动物数据更复杂)。

我可以像这样使用它:

animals.get([species:'Dog', gender:'M'])

返回:

[['Sammy', 'Mutt'], ['Taco', 'Husky'] ]

我想我知道如何实现它,所以我并不是真的在寻找它(尽管如果您有一个新颖的建议,请分享)。我主要是想找人告诉我,要么由于某种原因这不起作用,要么听起来不错,要么无法扩展,等等。或者也许有一些更简单的方法来获得类似的功能。还有一个考虑因素:整个数据集有时可能会很大,例如很少有 100k 条记录。如果不是这样,除了每次都点击数据库之外,还有什么好方法来处理它?

我意识到周围有很多键/值缓存解决方案,但我认为我不需要任何如此繁重的任务来完成我正在做的事情。它只是一个使用率很低的小型网络应用程序,主要是我为其构建的公司内部的。

Heres's something I'm thinking about doing, and I want to know if you think it's a good idea or not.

I retrieve a bunch of rows from a database, which in groovy gives me a list of lists something like:

[
  [ 'Dog', 'M', 'Mutt', 'Sammy' ],
  [ 'Cat', 'F', 'Siamese', 'Pat' ],
  [ 'Dog', 'M', 'Husky', 'Taco' ],
  ...
]

Not my real data set but you get the idea.

Since I will be pulling this data pretty frequently and doing some analysis to it before presenting it in the UI, I want to store it in a MultiValueMap keyed by groovy maps (i.e. LinkedHashMaps), so I can retrieve the bits and pieces of it that I need, without going to DB every time. It's kind of a cache of a subset of data that comes from several tables (more complex than the animals data above).

I would be able to use it like this:

animals.get([species:'Dog', gender:'M'])

returns:

[['Sammy', 'Mutt'], ['Taco', 'Husky'] ]

I think I have some idea how to implement it, so I'm not really looking for that (though if you have a novel suggestion please share). I'm mainly looking for somebody to tell me that either this won't work for some reason, or it sounds fine, or it won't scale, etc. Or maybe there's some easier way to get a similar functionality. One more consideration: the whole data set can sometimes be sorta large-ish, e.g. few 100k records. If not this, what's a good way to deal with it, aside from hit the DB every time?

I realize there are lots of key/value caching solutions around, but I don't think I need anything so heavy duty for what I'm doing. It is just a small webapp with pretty low usage, mostly internal to the company I'm building it for.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无尽的现实 2024-12-07 07:12:11

如果您使用的值的子集是静态/确定性的,我只需将其转换为字符串并将其用作映射中的键。因此,我不会使用 animals.get([species:'Dog', sex:'M']),而是使用 animals.get('species:Dog:gender:M')

我知道您说过您认为键值存储太重量级,但这也是 Redis 的完美用例,它可以 本地存储哈希映射等内容

您所说的存储类型正是我们在我工作的生产环境中使用它的方式,而且非常棒。它非常快,并且可以供所有正在运行的进程使用,而无需拥有单个或非常大的映射的多个副本。缓存失效也是您需要考虑的问题,redis 可以帮助解决。

您可以使用grails-redis插件来记住您的数据库调用,以便它首先自动检查redis查看它是否在缓存中,如果不在,它会查询数据库并将其放入缓存中,然后返回。有关更多详细信息/示例,请参阅 github 上的文档

return redisService.memoizeHash('species:Dog:gender:M') {
    // database call that returns object, then you turn that into hash
    Dog d = Dog.findBy...
    [species: d.species, gender: d.gender, breed: d.breed, name: d.name, ...]
}

这样,仅当 Redis 缓存中尚未有数据库时,它才会查询数据库。当缓存未命中时,它将返回值保存在 Redis 中的指定键处。

(免责声明,我是 grails-redis 插件 的作者,所以我有一些偏见)

If the subset of values you're using is static/deterministic, I'd just turn that into a string and use that as the key in your map. So instead of animals.get([species:'Dog', gender:'M']), I'd use animals.get('species:Dog:gender:M').

I know you said that you were thinking that a key-value store is too heavyweight, but this is also the perfect kind of use case for Redis, which can natively store things like hash maps.

The kind of cache that you're talking about storing is exactly how we use it in production where I work, and it's been great. It's very fast, and makes it available to all running processes without having to have a singleton, or multiple copies of very large maps. Cache invalidation is also something you'd need to think about that redis helps to solve.

You can use the grails-redis plugin to memoize your database calls, so that it automatically checks redis first to see if it's in the cache, if it isn't, it queries the database and sticks it in the cache before returning it. See the docs on github for more details/examples.

return redisService.memoizeHash('species:Dog:gender:M') {
    // database call that returns object, then you turn that into hash
    Dog d = Dog.findBy...
    [species: d.species, gender: d.gender, breed: d.breed, name: d.name, ...]
}

This way, it queries the database only if Redis doesn't already have it in cache. On cache miss, it saves the return value in redis at the specified key.

(Disclaimer, I'm the author of the grails-redis plugin, so I've got some bias)

潜移默化 2024-12-07 07:12:11

使用可变的 Map 作为键是一个非常糟糕的主意,因为如果键发生变化,那么它就不会被发现。

Using a mutable Map as a key is a really bad idea, because if the key changes then it will not be found.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文