1

我是 RavenDB 的新手,尝试让 Any() LINQ 查询正常工作一直令人沮丧。这是我的文档的样子:

{
  "Key": "BKey",
  "Text": "B Key",
  "IsLocal": false,
  "Category": null,
  "_destroy": false,
  "Translations": [
    {
      "CultureCode": "es-ES",
      "Text": null
    },
    {
     "CultureCode": "ja-JP",
     "Text": "Hello"
    }
  ]
}

我希望以下查询能给我所有没有“es-ES”翻译的条目:

var nonTranslatedEntries = 
_docs.Query<ResourceEntry>().Where( e => e.Translations == null || e.Translations.Count == 0 || !e.Translations.Any(t => t.CultureCode == "es-ES" && t.Text != null))

但是,这是行不通的。即使存在指定 CultureCode 的翻译,它也会带回条目。如果我在翻译数组中只有一项,它就可以工作。但是,一旦翻译数组中有多个项目,查询就会停止工作。

作为替代解决方案,我尝试执行以下操作:

var translatedEntries =  from re in _docs.Query<ResourceEntry>()
                                    where re.Translations.Any(t => t.CultureCode == cultureCode && t.Text != null)
                                    select new {Id = re.Id};
var translatedIds = translatedEntries.ToList().Select(e => e.Id).ToList();

var nonTranslatedEntries = 
  _docs.Query<ResourceEntry>().Where(e => !e.Id.In(translatedEntryIds));

但这只会带回一个空列表。

任何帮助将不胜感激。

谢谢,

尼扎尔

4

2 回答 2

1

将完成工作的静态索引:

public class Resources_ByTranslation : 
    AbstractIndexCreationTask<ResourceEntry, Resources_ByTranslation.IndexEntry>
{
    public class IndexEntry
    {
        public string Key { get; set; }
        public string CultureCodes { get; set; }
    }

    public Resources_ByTranslation()
    {
        Map = entries => from entry in entries
                         select new {
                                     entry.Key,
                                     CultureCodes = entry.Translations
                                                     .Where(x => x.Text != null)
                                                     .Select(x => x.CultureCode)
                                    };
    }
}

然后查询:

var nonTranslatedEntries =
    session.Query<Resources_ByTranslation.IndexEntry, Resources_ByTranslation>()
           .Where(x => x.CultureCodes != "es-ES")
           .As<ResourceEntry>();

请注意,CultureCodes 列表被视为单个字符串。这是由于索引匹配在内部是如何工作的。这有点奇怪,但它确实有效。

于 2012-11-21T16:56:02.353 回答
0

我最终解决了我的问题,如下所示:

创建资源条目后,我继续创建所有可能的翻译并将翻译文本设置为 null:

{
  "Key": "BKey",
  "Text": "B Key",
  "IsLocal": false,
  "Category": null,
  "_destroy": false,
  "Translations": [
    {
      "CultureCode": "es-ES",
      "Text": null
    },
    {
     "CultureCode": "ja-JP",
     "Text": null
    }
  ]
}

然后我创建了以下索引:

public class ResourceEntries_ByCultureCodes : AbstractIndexCreationTask<ResourceEntry>
    {
        public ResourceEntries_ByCultureCodes()
        {
            Map = entries => from e in entries
                             select new
                                 {
                                     e.Id,
                                     e.Key,
                                     e.Text,
                                     e.IsLocal,
                                     e.Category,
                                     _ = e.Translations.Select(t => CreateField(t.CultureCode, t.Text != null, false, true))
                                 };
        }
}

如果存在针对该特定文化的翻译,这给了我一个平坦的翻译记录,其值设置为“真”。例如,我得到这样的东西:

{ 
   Id,
   Key,
   Text,
   IsLocal,
   Category,
   es-ES: <true> or <false> depending upon whether Translation.Text != null
   ja-JP:<true> or <false> depending upon whether Translation.Text != null
}

然后我可以按如下方式执行 LuceneQuery 以获取所有未翻译的“es-ES”条目:

_docs.LuceneQuery<ResourceEntry, ResourceEntries_ByCultureCodes>().WhereEquals("es-ES", false);

不过,我希望有一个更简单的解决方案。

于 2012-11-22T16:22:40.233 回答