在我的数据库中,我有这样的图像:
{
"id": "image-1",
"type": "image",
"href": "..."
}
包含图片的书籍:
{
"id": "book-1",
"type": "book",
"images": [
"image-1",
"image-33"
]
}
这是一种多对多关系,因为相同的图像可以出现在多本书中,使用“按键列表”模式进行建模。我可以使用一个视图来遍历另一个方向的关系,并找到给定图像出现的书籍。
我的问题是:如何查找未出现在任何图书中的图像?
图像占用空间并可能有其他相关成本,因此这些成为删除的理想选择。
我的第一个想法是使用一个视图来计算每个图像的引用数量:
"map": function (doc) {
if (doc.type == "book") {
for (i = 0; i < doc.images.length; i++) {
emit(doc.images[i], null);
}
}
else if (doc.type == "image") {
emit(doc._id, null);
}
},
"reduce": _count
如果我说图像引用自身,那么我可以确定视图中存在所有图像,我只需要选择那些仅由它们自己引用的图像,即计数为1的位置。但是那个我被卡住了,因为视图机制似乎只让我过滤掉密钥,而不是值(计数)。
我还考虑针对book.images
成员创建索引,然后搜索不会出现在该索引中的图片,但我找不到这些行中的任何示例。
我知道我的潜在解决方案都需要对所有图像进行线性搜索,但我可以正确搜索,因为这是一种偶尔运行并且不是时间关键的内务处理操作。在这个程度上,我的第一个选项运行得很好,它只是意味着我必须将整个视图拉回客户端并在那里搜索我希望在服务器中应用过滤器。
我也知道如果我要更改模型并反转关系,以便图像包含书籍列表:
{
"id": "image-1",
"type": "image",
"href": "...",
"books": [
"book-1",
"book-12"
]
}
然后我仍然可以使用视图在书中找到图像,但我也可以索引image.books
成员并快速找到长度为0的那些。但是,这会给应用程序带来负担,因为应用程序编辑书籍,这意味着每当用户修改书籍中的图像时,应用程序还必须修改图像,这会引入一致性问题,因为使用不同书籍的两个用户最终可能会修改相同的图像。
答案 0 :(得分:0)
另一种方法是使用分面搜索并仅返回计数。它仍将返回每个图像。有效负载看起来像这样:
{
"total_rows": 4,
"bookmark": "g2o",
"rows": [ ],
"counts": {
"image": {
"image-1": 3.0,
"image-2": 1.0,
"image-33": 1.0
}
}
}
设计文档看起来像这样:
{
"_id": "_design/bookSearch",
"_rev": "xxx",
"views": {},
"language": "javascript",
"indexes": {
"search": {
"index": "function (doc) {\n if (doc.type == \"image\") {\n index(\"image\", doc.id, {\"facet\": true});\n }\n else if (doc.type == \"book\") {\n for (var i=0; i<doc.images.length; i++) {\n index(\"image\", doc.images[i], {\"facet\": true});\n }\n }\n}\n",
"analyzer": "standard"
}
}
}
功能如下:
function (doc) {
if (doc.type == "image") {
index("image", doc.id, {"facet": true});
}
else if (doc.type == "book") {
for (var i=0; i<doc.images.length; i++) {
index("image", doc.images[i], {"facet": true});
}
}
}
查询看起来像这样:
https://xxx.cloudant.com/db/_design/bookSearch/_search/search
?q=*:*&limit=0&counts=["image"]
虽然不确定这样做是否有任何实际优势......