Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用MongoDB的按位枚举(标志)查询';s官方C#driver_C#_Linq_Mongodb_Mongodb .net Driver_Bitwise Operators - Fatal编程技术网

使用MongoDB的按位枚举(标志)查询';s官方C#driver

使用MongoDB的按位枚举(标志)查询';s官方C#driver,c#,linq,mongodb,mongodb-.net-driver,bitwise-operators,C#,Linq,Mongodb,Mongodb .net Driver,Bitwise Operators,当我尝试运行表单的LINQ查询时: MongoCollection集合; collection.AsQueryable().Where(entity=> (entity.Flags和MyFlags.AFlag)!=MyFlags.None); 我得到一个ArgumentException,其中包含消息Unsupported where子句:((Int32)((Int32)entity.Flags&4)!=0)。 这是已知的错误/功能吗? 有解决办法吗? 从外观上看,MongoDB似乎有一个按位

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

MongoCollection集合;
collection.AsQueryable().Where(entity=>
(entity.Flags和MyFlags.AFlag)!=MyFlags.None);
我得到一个
ArgumentException
,其中包含消息
Unsupported where子句:((Int32)((Int32)entity.Flags&4)!=0)。

这是已知的错误/功能吗?

有解决办法吗?

从外观上看,MongoDB似乎有一个按位更新,但没有按位查询

相比之下,相同的查询在使用ServiceStack作为客户机的Redis上平稳运行

但是,我确实发现这两个链接(,)建议使用JavaScript,这将使服务层的实现非常依赖于DB技术。

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

public static IQueryable<TItem> HasFlags<TItem, TProperty>(
    this IQueryable<TItem> items,
    Expression<Func<TItem, TProperty>> itemPropertyExpression,
    params Enum[] enumFlags)
{
    var enumFlagNames = enumFlags.Select(enumFlag => (BsonValue)enumFlag.ToString());
    return items.Where(item => Query.In(ExtendedObject.GetPropertyName(itemPropertyExpression), enumFlagNames).Inject());
}
公共静态IQueryable HasFlags(
这是一个易读的项目,
表达式itemPropertyExpression,
参数枚举[]枚举标志)
{
var enumFlagNames=enumFlags.Select(enumFlag=>(BsonValue)enumFlag.ToString();
返回items.Where(item=>Query.In(ExtendedObject.GetPropertyName(itemPropertyExpression),enumFlagNames.Inject());
}
这样,它既可读又不需要将所有对象反序列化到内存中

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

public static string GetPropertyName<TClass, TProperty>(
    Expression<Func<TClass, TProperty>> entityPropertyExpression)
{
    return ((MemberExpression)entityPropertyExpression.Body).Member.Name;
}
公共静态字符串GetPropertyName(
表达式entityPropertyExpression)
{
返回((MemberExpression)entityPropertyExpression.Body).Member.Name;
}

从MongoDB v 3.2开始,您可以使用,也可以根据您搜索的内容使用

因此,使用C#MongoDB驱动程序:

//Check single Flag as OP
collection.Find(Builders<MyEntity>.Filter.BitsAllSet(myEntity => myEntity.Flags, (long) MyFlags.AFlag));

//Check all multiple Flags
collection.Find(Builders<MyEntity>.Filter.BitsAllSet(myEntity => myEntity.Flags, (long) MyFlags.AFlag | MyFlags.BFlag));

//Check any multiple Flag
collection.Find(Builders<MyEntity>.Filter.BitsAnySet(myEntity => myEntity.Flags, (long) MyFlags.AFlag | MyFlags.BFlag));
//将单个标志检查为OP
Find(Builders.Filter.BitsAllSet(myEntity=>myEntity.Flags,(long)MyFlags.AFlag));
//检查所有多个标志
collection.Find(Builders.Filter.BitsAllSet(myEntity=>myEntity.Flags,(long)MyFlags.AFlag | MyFlags.BFlag));
//检查任意多个标志
collection.Find(Builders.Filter.BitsAnySet(myEntity=>myEntity.Flags,(long)MyFlags.AFlag | MyFlags.BFlag));

注意:在按位操作上使用索引有一种方法。在MongoDB 4.2上,他们仍然没有使用它们,所以如果你打算大量使用它们(我们曾经是,后来我们不得不重构一切)。

也许你可以尝试使用linq来反对查询:collection.AsQueryable().ToList().Where(entity=>(entity.Flags&MyFlags.AFlag)!=MyFlags.None);这将把所有对象反序列化到内存中。不过,我可以在其他过滤器之后使用它(假设它们足够减少记录)。@Tim.Tang这适用于我的查询,因为我有其他条件可以预先过滤。还注意到GroupBy()失败,需要移动到after.ToList()。请注意,如果您想处理点表示法等,您需要一个更健壮的
GetPropertyName