YOLO813

数据库的设计教训-预留字段

    最近碰到一些麻烦的问题,就是国外的用户经常会要求删除数据,这个其实解决起来不麻烦,数据库把这条数据删除就可以了,但是如果:你的数据是程序自动循环更新的,该怎么办呢?毕竟你也不想下一次更新时,又将该条数据插入到数据库,所以,最好的解决方案就是预留一个字段,专用于控制网站页面是否展示!

    我的整个网站架构大概分为Linux服务器-nginx(web服务器)-mysql数据库(暂存数据)-elasticsearch(展示、搜索数据),之前在记录MYSQL同步数据至ES的测试历程一文中介绍过,我采用的logstash同步mysql到elasticsearch的数据属于增量同步,也就是删除是无法同步过去的,因此这也决定了我采用自定义字段来控制页面内容。

    首先停掉logstash的数据同步,新建202202bak索引,建立相同mapping结构,备份数据,

POST /_reindex?wait_for_completion=false
{
  "source": {
    "index": "2021"
  },
  "dest": {
    "index": "2022bak"
  }
}


    我采用的是异步同步数据,这会返回一个task ID,可以用于查看数据完成情况。

    由于数据量过大,所以我没有采用直接修改mysql的字段内容让logstash再同步到elasticsearch,而是直接修改elasticsearch的字段内容,这个处理过程快很多

POST 2021/_update_by_query
{
  "script": {
    "source": "ctx._source['status'] = 'Y'"
  }
}


    再去修改数据库里面的该字段内容,这个status字段本就是我创建备用的字段,并且我事先为其增加了索引,后面的WHERE status IS NULL语句如果没有添加,那么在修改时其实并没有利用到索引(Navicat的explain)

UPDATE table SET status="Y" WHERE status IS NULL

    一切就绪之后,再去表里面随便修改一条数据,拿到它的最新“更新时间”,将其转化成时间戳,覆盖logstash配置文件中的定义的字段last_run_metadata_path的文件内容,这样做的原因在于再次重启logstash之后其不会再傻乎乎的同步mysql的数据到elasticsearch中,它只会记录该时间戳之后的数据更改。

    最后修改elasticsearch操作文件,只需在最上级添加一行代码,从此只要该字段不为Y,则该条数据不会被展示,以下status字段对应的mapping结构type为keyword

from elasticsearch import Elasticsearch
client = Elasticsearch()
my_client = Search(using=client, index="2021")
# 添加的代码
my_client = my_client.filter('term', status='Y') 


    到这里基本就完工了,但是因为我的站点地图文件内容还是取之于数据库,所以在站点地图的处理逻辑里面也要补上这个漏洞:

# sitemaps.py
class NBASitemap(LimitSitemap):
    changefreq = "weekly"
    priority = 0.6
    def items(self):
        # return NBA.objects.order_by("id") 原来的
        return NBA.objects.filter(status="Y").order_by("id")
    def location(self, obj):
        return reverse("nba:detail",args=[obj.number])
    def lastmod(self, obj):
        return obj.update_time

在所有的objects后面添加这个过滤即可。