The paper describes a rule-based query optimizer for object-oriented databases. The originality of the approach is through a multi-level logic programming used to model the variety of knowledge contained in the query optimizer in an explicit, declarative and transparent way. Our approach offers means of abstraction for expressing various kinds of knowledge involved in a query optimizer. It also offers techniques for structuring them according to both generality levels and knowledge content, i.e. meta-levels. We present a programming technique that allows to write modules which can be at various meta-levels. To illustrate these ideas, we show how multi-level programming can be used to model a query optimizer for an object-oriented database. Among the various kinds of knowledge involved, we have (besides the queries themselves - first or object level) techniques for query manipulations and transformation, as well as cost models (second or meta- level), techniques for combining transformations, search strategies, techniques for cost model selection (third or meta-meta- level), and optimization plans (fourth level). The optimizer architecture based on this model is presented.