So what is happening here is that pg_indexes has 4 rows matching your WHERE conditions. When you LEFT JOIN, you keep all rows even if there is no join. In your case, only one row joins pg_constraint.
When a LEFT JOIN fails to connect a row, it fills all of the would-be columns with NULL. This means that in your case, the 3 rows that did not join pg_constraint now have NULL for all columns specified by pg_constraint.
Lastly, when it comes to your comparison of ____ <> 'p', you are missing a rule for how SQL treats NULL values. NULL is treated as the absence of value rather than something you can compare to. Any attempt to use a scalar comparison will fail.
You can correct this by changing to WHERE (pc.contype IS NULL OR pc.contype <> 'p')