bookmark_border我们总是忘记在机场要拥抱

我大概是在看到床上叠好的衣服的时候开始哭的,这是我人生中最与众不同的四十天。在距离家上万公里的地方,在一个我租来的家里,我们一家在一起住了四十天。

起初只是哽咽,再是抽泣,最后竟也哭出了声。平凡这个词向来听起来不是一个好的形容词,但当有一个“平凡”的父母在以“平凡”的方式一直爱着你时,这无疑是世界上最伟大的事。我与父母三年有余未见,也是我从出生至今,自己不依赖父母过得最长的一段时间了。平复心情后来讲,这三年绝构不上艰辛和痛苦,在人生过得最快的几年里,我颇有逃离意味地在异乡度过了三年,反观父母在每次与我的视频里,在每次微信聊天里,却从未谈及这三年里,他们的生活与工作。便是最基本的关心,我都轻易地拿工作忙的借口帮自己搪塞过去了。

故而在这一起相处的四十天里,我,一个第一次做儿子的人,和我的父母,第一次当父母的两个人,不出意外地在不停地拉扯。这种拉扯我不知道是好是坏,但却是让我一瞬间就感受到穿越回万里外家乡的感觉。这种拉扯包括但不限于日常琐碎的争吵,一言不发的奉献,千叮咛万嘱咐和无法言语的感情。这种拉扯,在某种意义上来说,就是系在我和父母身上那永不可磨灭与忽视的绑带,是跨越了空间和时间的,无法用这世间任何度量单位去衡量的绑带。

当飞机延着跑道起飞,我沿着高速公路回到家里,我打开了家里所有的灯,一盏一盏的比较着,我渴望找到那盏色温最暖的灯,可今天的家里格外的冷,我或许该要去把空调打开了。

bookmark_borderMongoDB index with multiple filters

Recently, my current project has faced some loading issue with mongodb, to be specific, documentdb from AWS. We have mid-level instance and a lot of collection for data seperation purpose. For some of collections, it store more than millions data.

Our data structure like this:

type Course struct {
    ClassType int
    Prerequirement []*Course
    Teacher string // should be a Teach but for simplicity using string here.
    BuildNumber int
    
}

type Student struct {
    Grade int
    AdmittedAt time.Time
    StartedAt time.Time
    GraduationTime time.Time
    CoursesJoined []*Course
}

The data structure is just a mock, to clarify the function of indexes, we will consider some scenario later.

Before we jump into the index, we should know the basic index concept and when/where/how to create an index which is an index strategy.

I will skip when and where here, but want to emphasize ‘How to create an effective index’

The ESR (Equality, Sort, Range) Rule

Equality

“Equality” refers to an exact match on a single value. The following exact match queries scan the cars collection for documents whose model field exactly matches Cordoba.

db.cars.find( { model: "Cordoba" } )db.cars.find( { model: { $eq: "Cordoba" } } )

Index searches make efficient use of exact matches to limit the number of documents that need to be examined to satisfy a query. Place fields that require exact matches first in your index.

An index may have multiple keys for queries with exact matches. The index keys for equality matches can appear in any order. However, to satisfy an equality match with the index, all of the index keys for exact matches must come before any other index fields. MongoDB’s search algorithm eliminates any need to arrange the exact match fields in a particular order.

Exact matches should be selective. To reduce the number of index keys scanned, ensure equality tests eliminate at least 90% of possible document matches.

Sort

“Sort” determines the order for results. Sort follows equality matches because the equality matches reduce the number of documents that need to be sorted. Sorting after the equality matches also allows MongoDB to do a non-blocking sort.

An index can support sort operations when the query fields are a subset of the index keys. Sort operations on a subset of the index keys are only supported if the query includes equality conditions for all of the prefix keys that precede the sort keys. For more information see: Sort and Non-prefix Subset of an Index.

The following example queries the cars collection. The output is sorted by model:

db.cars.find( { manufacturer: "GM" } ).sort( { model: 1 } )

To improve query performance, create an index on the manufacturer and model fields:

db.cars.createIndex( { manufacturer: 1, model: 1 } )
  • manufacturer is the first key because it is an equality match.
  • model is indexed in the same order ( 1 ) as the query.

Range

“Range” filters scan fields. The scan doesn’t require an exact match, which means range filters are loosely bound to index keys. To improve query efficiency, make the range bounds as tight as possible and use equality matches to limit the number of documents that must be scanned.

Range filters resemble the following:

db.cars.find( { price: { $gte: 15000} } )db.cars.find( { age: { $lt: 10 } } )db.cars.find( { priorAccidents: { $ne: null } } )

MongoDB cannot do an index sort on the results of a range filter. Place the range filter after the sort predicate so MongoDB can use a non-blocking index sort. For more information on blocking sorts, see cursor.allowDiskUse().

Please keep these three words in your mind until you find a job that completely is irrelated to development, of course, until you win the power ball as well.

So we can start to think about several cases:

We want to find all students that are in Grade 1 and admitted in past 6 weeks, then sorted by start date descending.

at this case, we know Equality is grade, and Sort is the start time, the time range is based on admitted time, so we can easily create an index

{grade:1, admitted_at: -1, started_at:-1}

But the requirement changed a lot. For some reason, the principal wants to know all school students instead of Grade 1, because of the index prefix mechanism in MongoDB (https://www.mongodb.com/docs/manual/core/index-compound/#prefixes) without grade, this index won’t be hit when searching only by admitted time and start time.

In this case, we may want to change the index to

 {admitted_at: -1, started_at:-1, grade:1}. 

But for the same reason, it will request every query need to contain a prefix to take advantage of the index.

We want to find all students that have Type A course and That course’s teacher is Weihao and admitted in past 6 weeks, then sorted by start date descending.

In this case, cause we have a subdocument in our data structure, we need to create an index for the subdocument as well. So the index will looks like

{courses_joined.class_type:1, courses_joined.teacher:1, admited_at:-1, started_at:-1}

We still try to use a compound index to fulfill the requirement, which is good for extensibility but also bad for extensibility. Imagine one more scenario, what if someday the product manager asks you when the department of education has issued a new law that doesn’t allow searching students much specific. So you have to change the AND relation between course_joined.class_type and course_joined.teacher to OR relation. Then you find out the index is not hitting anymore as OR aggregation requires both fields have an independent index.

In this case, we should create multiple indexes and use MongoDB index intersection

{admited_at:-1, started_at:-1}
{courses_joined.class_type:1}
{courses_joined.teacher:1}

Other MongoDB article:

bookmark_borderCaltrain的终点站是下元

从SFO 飞到 JFK的航班要5个半小时,我记得在上次回国的飞机上,我洋洋洒洒写了几千字,只为探究我是在哪一个时区跨过了2019年和2020年。现在想想那时是天真的可爱,转念一想当时的记录也算弥足珍贵了。可惜的是后来我发现找不到那篇文章写在哪了。原来2019真的回不去了。

网络上有人在一年前把当时称作“后疫情时代”,罗列了20年和21年漫长的疫情时间线,并盖棺定论般地说:当时处在“后疫情时代”的我们,会永远铭记这漫长历史上沾满冠状病毒的两年。或许是结论下的太早的原因,后来又将“后疫情时代”改成了“中疫情时代”。

说来惭愧,竟是不知不觉滑到了中年人的行列,倒真不是年龄的累加在身后催促,反而是因为在不知不觉中发现自己开始享受晚上8点窝在沙发上看电视,同时不用担心错过提交的作业。起初会咬牙切齿恨每天的日子会不经意被各种事情充斥,甩也甩不掉,做了也不会有成就感,后来不论是说释然了还是妥协了,但总算搞明白了的是:成就感这个东西,远比不上赌博和情爱的快感。与其说成年人是无聊无趣的,究其根本是比赛刚进入了白热化,作为选手的你却发现自己没报名而已。会看着远处的骄子们痛心疾首,也会和给你加油的朋友打气说重在参与。

回到这架目的是约翰肯尼迪机场的飞机上,如果这世上有人总结过,每一次出行的路上都是最好的内省时机。我必定跨过时间和空间的限制,去和他/她拥抱一下,然后问问,后半句是不是:在路上的内省深刻且准确,但是到达目的地后就会置之脑后。

因为工作的变动,之前和人打交道的生活变成了和摄像头打交道,当然不是指无休止的居家办公和Zoom meeting,而是挂在你背后天花板角落的那个黑色监工。工作的变动无可厚非,毕竟没有哪个工地能搬一辈子的砖,在哪里敲代码不是敲代码,写bug亦同,debug亦同。真正让人唏嘘的是看到自己慢慢拼凑起来的产品有一天再和自己毫无瓜葛,颇有一种霸王别姬的气质,唯一区别可能是楚霸王自刎于吴江边,我则是搭着江上的小舟去找下一个姬了。反倒是我的虞姬活了下来,成了那个独自面对这个喧哗世界的人了。坦白来讲,能够做出一个被数十万人使用的产品,可以和赌博和情爱并列了。

飞机总会遇到气流,上上下下晃来晃去,没想到我在离开母亲肚子二十多年后,还是会因为飞机的晃动产生困意。说起母亲,大概算来也有约834天没有见面了,最近视频的次数愈来愈多了,不知是她开始想我了,还是我开始想她了。该死的疫情!竟成了最好的借口,竟能压过无时无刻不在的思念,不知母亲有没有后悔数年前在海底捞排位时,轻易答应我出国的请求。在茂业百货的顶楼,我不知道那家海底捞现在还在不在,只记得他们的等位区竟是连美国的都不如,厚重的帘子还是挡不住太原的冷风,没有吹醒本就愚钝的我和一时失神的母亲,可没想到连头脑一向冷静的爸爸也一并同意了。该死的海底捞!

如果生活像起飞的飞机一样就好了,在起飞的时候,唯一的目的就是降落在目的地。时常会辗转反侧,原因也无他,挣扎于目的地而已,别人都在爬升的时候,还在盘旋的人却已经在考虑降落了,不知道是谨慎还是他们的苍穹太低了。

记得小时候去二姨家,要先穿过院子,再横跨12车道的迎泽大街,在省人大坐上1路公交车,投币一元,刷学生卡只要两毛五,约莫十站后,终点站下元到了,转乘摩的,我被夹在妈妈和摩的师傅之间,摩托在下元的人流里穿梭,几分钟之后就会把下元远远的甩在身后。与此同时,1路公交调转车头,始发站下元,终点站太原火车站,投币一元,刷卡七毛五。

bookmark_border嘿!妈妈

嘿妈妈

明天我就要出发了

出发去远方冒险

在那个太阳初升的清晨六点


嘿妈妈

今天到了新的城市

这里路很窄房子却很大

听说年轻时你也来过这里是吗?


嘿妈妈

昨天遇到了一个姑娘

她笑起来很甜

我们谈了很多,包括未来和理想


嘿妈妈

最近我又换了住所

往西搬了三个街区

和佳还是差十二个时区


嘿妈妈

故事还在继续

像微风清徐

在月下轻语

bookmark_border随笔

写一些不知所以的故事吧,在自己还未搞清世界和人生的时候。

出发的时候最忌讳回头,即使你知道背后还有人在看着你。

因为一些东西太容易被抹去了,所以才劝你一定要留下些什么。

写些不算道理的道理,都是前人所想,换个说法罢了

bookmark_borderAWS Lightsail WordPress SSL 证书一键renew

sudo /opt/bitnami/bncert-tool

AWS Lightsail WordPress的instance已经提前安装好了 bncert-tool, 如果之前已经配置过一次SSL的DNS records 和开启了HTTPS的话,遇到证书过期,只需要执行上面的command。然后他自动跑完之后就会签发证书了

2021-09-23 update

这两天发现之前的认证又失效了,于是准备继续去renew certificate,但是在跑的时候发现会报错说certificate expire,查了很久,刚开始觉得这个是一个悖论,因为expire所以需要renew,但是因为expire又不能renew。 实在头大,后来发现bitnami其实有自己的letencrypt的证书存储地址,所以在/etc/letencrypt/下面的证书并不会生效

最终的解决办法就是把 /opt/bitnami/letencrypt/certificate 下的证书删掉,重新跑就好了

这里我第二次授权的时候使用的是lego,但其实应该certbot也是可以的,只要确保过期的证书被删掉就好

lego在生产证书的时候,会自动生成在./.lego/certificate,所以还需要拷贝到对应的bitnami放证书的地方

doc:

https://go-acme.github.io/lego/usage/cli/examples/

https://docs.bitnami.com/general/how-to/generate-install-lets-encrypt-ssl/

2022-03-04 update
又踩了一个坑,因为renew报错显示需要先revoke 生效的certification,然后再重新申请,所以就直接删除了/opt/bitnami/letenscript/*, 然后发现apache直接down掉了,后来只能重新给apache生成了一个dummy的certificates,然后更改了bitnami的config,再重新生成就好了

https://docs.bitnami.com/aws/apps/wordpress/administration/create-ssl-certificate-apache/