使用MongoDB的官方C#驱动程序进行按位枚举(标志)查询

当我尝试运行表单的LINQ查询时:

MongoCollection collection; collection.AsQueryable().Where(entity => (entity.Flags & MyFlags.AFlag) != MyFlags.None); 

我得到一个带有消息Unsupported where clause: ((Int32)((Int32)entity.Flags & 4) != 0).ArgumentException Unsupported where clause: ((Int32)((Int32)entity.Flags & 4) != 0).

这是一个已知的错误/function吗?

有没有解决方法?

从文档中可以看出,MongoDB有一个按位更新,但不是按位查询。

为了进行比较,使用ServiceStack作为客户端,相同的查询在Redis上方顺利运行。

我确实找到了建议使用JavaScript的这两个链接( link1 , link2 ),这将使服务层的实现非常依赖于DB技术。

我的解决方案有两个部分。 我为Enum标志创建了一个序列化器,它将所有值存储在字符串列表中。 我为Linq做了一个扩展方法,以“注入”我需要的mongo查询。

 public static IQueryable HasFlags( this IQueryable items, Expression> itemPropertyExpression, params Enum[] enumFlags) { var enumFlagNames = enumFlags.Select(enumFlag => (BsonValue)enumFlag.ToString()); return items.Where(item => Query.In(ExtendedObject.GetPropertyName(itemPropertyExpression), enumFlagNames).Inject()); } 

这样,它既可读也不需要将所有对象反序列化为内存。

PS:GetPropertyName方法只是一种获取属性名称的类型安全方法:

 public static string GetPropertyName( Expression> entityPropertyExpression) { return ((MemberExpression)entityPropertyExpression.Body).Member.Name; } 

从MongoDB v 3.2开始,您可以使用bitsAllSet或bitsAnySet,具体取决于您要搜索的内容。

所以,使用C#MongoDB驱动程序:

 //Check single Flag as OP collection.Find(Builders.Filter.BitsAllSet(myEntity => myEntity.Flags, (long) MyFlags.AFlag)); //Check all multiple Flags collection.Find(Builders.Filter.BitsAllSet(myEntity => myEntity.Flags, (long) MyFlags.AFlag | MyFlags.BFlag)); //Check any multiple Flag collection.Find(Builders.Filter.BitsAnySet(myEntity => myEntity.Flags, (long) MyFlags.AFlag | MyFlags.BFlag));