private static IMongoQuery CompositeQuery(ModelInfo.SearchParamDefinition parameterDef, Operator optor, String modifier, ValueExpression operand) { if (optor == Operator.IN) { var choices = ((ChoiceValue)operand); var queries = new List <IMongoQuery>(); foreach (var choice in choices.Choices) { queries.Add(CompositeQuery(parameterDef, Operator.EQ, modifier, choice)); } return(M.Query.Or(queries)); } else if (optor == Operator.EQ) { var typedOperand = (CompositeValue)operand; var queries = new List <IMongoQuery>(); var components = typedOperand.Components; var subParams = parameterDef.CompositeParams; if (components.Count() != subParams.Count()) { throw new ArgumentException(String.Format("Parameter {0} requires exactly {1} composite values, not the currently provided {2} values.", parameterDef.Name, subParams.Count(), components.Count())); } for (int i = 0; i < subParams.Count(); i++) { var subCrit = new Criterium(); subCrit.Type = Operator.EQ; subCrit.ParamName = subParams[i]; subCrit.Operand = components[i]; subCrit.Modifier = modifier; queries.Add(subCrit.ToFilter(parameterDef.Resource)); } return(M.Query.And(queries)); } throw new ArgumentException(String.Format("Invalid operator {0} on composite parameter {1}", optor.ToString(), parameterDef.Name)); }
private static IMongoQuery DateQuery(String parameterName, Operator optor, String modifier, ValueExpression operand) { if (optor == Operator.IN) { IEnumerable <ValueExpression> opMultiple = ((ChoiceValue)operand).Choices; return(M.Query.Or(opMultiple.Select(choice => DateQuery(parameterName, Operator.EQ, modifier, choice)))); } string start = parameterName + ".start"; string end = parameterName + ".end"; var typedOperand = ((UntypedValue)operand).AsDateValue(); var value = GroomDate(typedOperand.Value); switch (optor) { case Operator.EQ: return (M.Query.Or( M.Query.Matches(parameterName, "^" + value), M.Query.And( M.Query.Or(M.Query.Exists(start), M.Query.Exists(end)), M.Query.Or(M.Query.LTE(start, value), M.Query.NotExists(start)), M.Query.Or(M.Query.GTE(end, value), M.Query.NotExists(end)) ) )); case Operator.GT: return (M.Query.Or( M.Query.GT(parameterName, value), M.Query.GT(start, value) )); case Operator.GTE: return (M.Query.Or( M.Query.GTE(parameterName, value), M.Query.GTE(start, value) )); case Operator.LT: return (M.Query.Or( M.Query.LT(parameterName, value), M.Query.LT(end, value) )); case Operator.LTE: return (M.Query.Or( M.Query.LTE(parameterName, value), M.Query.LTE(end, value) )); case Operator.ISNULL: return(M.Query.EQ(parameterName, null)); //We don't use M.Query.NotExists, because that would exclude resources that have this field with an explicit null in it. case Operator.NOTNULL: return(M.Query.NE(parameterName, null)); //We don't use M.Query.Exists, because that would include resources that have this field with an explicit null in it. default: throw new ArgumentException(String.Format("Invalid operator {0} on date parameter {1}", optor.ToString(), parameterName)); } }
private static IMongoQuery QuantityQuery(String parameterName, Operator optor, String modifier, ValueExpression operand) { var quantity = operand.ToModelQuantity(); Fhir.Metrics.Quantity q = quantity.ToSystemQuantity().Canonical(); string decimals = Units.SearchableString(q); BsonValue value = q.GetValueAsBson(); List <IMongoQuery> queries = new List <IMongoQuery>(); switch (optor) { case Operator.EQ: queries.Add(M.Query.Matches("decimals", new BsonRegularExpression("^" + decimals))); break; default: queries.Add(ExpressionQuery("value", optor, value)); break; } if (quantity.System != null) { queries.Add(M.Query.EQ("system", quantity.System.ToString())); } queries.Add(M.Query.EQ("unit", q.Metric.ToString())); IMongoQuery query = M.Query.ElemMatch(parameterName, M.Query.And(queries)); return(query); }
private static IMongoQuery TokenQuery(String parameterName, Operator optor, String modifier, ValueExpression operand) { string systemfield = parameterName + ".system"; string codefield = parameterName + ".code"; string displayfield = parameterName + ".display"; string textfield = parameterName + "_text"; switch (optor) { case Operator.EQ: var typedOperand = ((UntypedValue)operand).AsTokenValue(); switch (modifier) { case Modifier.TEXT: return(M.Query.Or( M.Query.Matches(textfield, new BsonRegularExpression(typedOperand.Value, "i")), M.Query.Matches(displayfield, new BsonRegularExpression(typedOperand.Value, "i")))); default: if (typedOperand.AnyNamespace) { return(M.Query.EQ(codefield, typedOperand.Value)); } else if (String.IsNullOrWhiteSpace(typedOperand.Namespace)) { return(M.Query.ElemMatch(parameterName, M.Query.And( M.Query.NotExists("system"), M.Query.EQ("code", typedOperand.Value) ))); } else { return(M.Query.ElemMatch(parameterName, M.Query.And( M.Query.EQ("system", typedOperand.Namespace), M.Query.EQ("code", typedOperand.Value) ))); } } case Operator.IN: IEnumerable <ValueExpression> opMultiple = ((ChoiceValue)operand).Choices; return(M.Query.Or(opMultiple.Select(choice => TokenQuery(parameterName, Operator.EQ, modifier, choice)))); case Operator.ISNULL: return(M.Query.And(M.Query.EQ(parameterName, BsonNull.Value), M.Query.EQ(textfield, BsonNull.Value))); //We don't use M.Query.NotExists, because that would exclude resources that have this field with an explicit null in it. case Operator.NOTNULL: return(M.Query.Or(M.Query.NE(parameterName, BsonNull.Value), M.Query.EQ(textfield, BsonNull.Value))); //We don't use M.Query.Exists, because that would include resources that have this field with an explicit null in it. default: throw new ArgumentException(String.Format("Invalid operator {0} on token parameter {1}", optor.ToString(), parameterName)); } }
private static IMongoQuery StringQuery(String parameterName, Operator optor, String modifier, ValueExpression operand) { switch (optor) { case Operator.EQ: var typedOperand = ((UntypedValue)operand).AsStringValue().ToString(); switch (modifier) { case Modifier.EXACT: return(M.Query.EQ(parameterName, typedOperand)); case Modifier.TEXT: //the same behaviour as :phonetic in previous versions. return(M.Query.Matches(parameterName + "soundex", "^" + typedOperand)); case Modifier.NONE: case null: //partial from begin return(M.Query.Matches(parameterName, new BsonRegularExpression("^" + typedOperand, "i"))); default: throw new ArgumentException(String.Format("Invalid modifier {0} on string parameter {1}", modifier, parameterName)); } case Operator.IN: //We'll only handle choice like :exact IEnumerable <ValueExpression> opMultiple = ((ChoiceValue)operand).Choices; return(M.Query.In(parameterName, new BsonArray(opMultiple.Cast <UntypedValue>().Select(uv => uv.AsStringValue().ToString())))); case Operator.ISNULL: return(M.Query.EQ(parameterName, null)); //We don't use M.Query.NotExists, because that would exclude resources that have this field with an explicit null in it. case Operator.NOTNULL: return(M.Query.NE(parameterName, null)); //We don't use M.Query.Exists, because that would include resources that have this field with an explicit null in it. default: throw new ArgumentException(String.Format("Invalid operator {0} on string parameter {1}", optor.ToString(), parameterName)); } }