I want to limit search to when username = "demo" or isPublic = 1
Initially I was using should for this:

should: [
term: {username: "demo"},
term: {isPublic: 1}
]

I quickly ran into some issues. I realized that should was simply improving scores for the results instead of restricting result? Which means entries with username = "demo" AND isPublic are ranked way higher. This is not what I want. I just want entries to fulfill these criteria.

A way would be to have something like must [username: "demo" OR isPublic: 1], but I can't seem to find something like this in the documentation.

If you're not interested in the scoring, you should use a filter context instead of a query context. This should give you the yes-or-no answer you're looking for. What version of ES are you using? The format for filter vs query changed significantly between 1.7 and 2.x.

Regarding the logic, yes it seems you need a nested boolean here. So something like: