Как динамически применить условный оператор к полю, используя официальный MongoDB-CSharp-Driver? - PullRequest
5 голосов
/ 17 января 2012

Я пытаюсь сгенерировать запрос, который находит все большие, красные вещи со стоимостью, превышающей 3.

Похоже, что этот запрос мне нужен:

{ "color" : "red", "size" : "large", "cost" : { "$gt" : 3.0 } }

Но я не могу найти элегантный способ создать условие стоимости, используя официальный драйвер MongoDB CSharp.Это один хак, который, кажется, создает запрос:

QueryConditionList gt = Query.GT("cost", BsonDouble.Create(3));

QueryDocument query = new QueryDocument();
query.Add("color", "red");
query.Add("size", "large");
query.Add(gt.ToBsonDocument().Elements);

List<BsonDocument> results = events.Find(query).ToList();

Другой способ сделать это, который работает, выглядит так:

QueryDocument query = new QueryDocument();
query.Add("color", "red");
query.Add("size", "large");
query.Add("cost", new BsonDocument("$gt", BsonDouble.Create(3)));

List<BsonDocument> results = events.Find(query).ToList();

Является ли любой из этих подходов хорошим способомчтобы сделать это?Есть ли другой?

Мне нужно использовать методы, которые позволяют мне динамически строить запрос и добавлять поля, которые будут задействованы в запросе.Я надеялся найти способ добавить условие с помощью query.Add (), но я не знаю, возможно ли это.

Любая помощь приветствуется.

Ответы [ 2 ]

6 голосов
/ 17 января 2012

Вы можете использовать конструктор запросов повсюду, например:

var query = Query.And(
              Query.EQ("color", "red"), 
              Query.EQ("size", "large"), 
              Query.GT("cost", 3)
            );

update Извините, теперь я вижу, что вы спрашиваете.

Вы можетесделайте что-то вроде этого также:

int i = 0;
var qc = QueryComplete[3];
qc[i++] = Query.EQ("color", "red");
qc[i++] = Query.EQ("size", "large");
qc[i++] = Query.GT("cost", 3);
var query = Query.And(qc);

Таким образом, вы все равно можете использовать методы построителя, и он будет динамическим.

2 голосов
/ 14 марта 2013

Вы можете использовать данные для перебора, просто построив дерево «QueryElement» и вызвав BuildQuery, чтобы рекурсивно построить его, как в примере этого класса:

    public class QueryElement
    {
        public enum eOperator
        {
            AND, OR, EQ, NE, GT, GTE, LT, LTE      //etc.
        };

        public eOperator Operator { get; set; }

        public string Field { get; set; }

        public BsonValue Value { get; set; }

        public List<QueryElement> Children { get; set; }

        public IMongoQuery BuildQuery()
        {
            int i = 0;
            var qc = new IMongoQuery[(Children!=null)?Children.Count:0];

            if (Children != null)
            {
                foreach (var child in Children)
                {
                    qc[i++] = child.BuildQuery();
                }
            }

            switch (Operator)
            {
                // multiple element operators

                case eOperator.AND:
                    return Query.And(qc);
                case eOperator.OR:
                    return Query.And(qc);

                // single element operators
                case eOperator.EQ:
                    return Query.EQ(Field, Value);
                case eOperator.NE:
                    return Query.NE(Field, Value);
                case eOperator.GT:
                    return Query.GT(Field, Value);
                case eOperator.GTE:
                    return Query.GTE(Field, Value);
                case eOperator.LT:
                    return Query.LT(Field, Value);
                case eOperator.LTE:
                    return Query.LTE(Field, Value);
            }
            return null;
        }
    }
...