سؤال

لدي فئة مستندات تحتوي على قائمة "العلامات". شيء مثل:

class Item {
  string Name { get; set; }
  List<string> Tags {get; set;}
}

الآن أود إنشاء استعلام لـ Ravendb يمسحني جميع العناصر التي تمت ترشيحها بقائمة من العلامات. عند استخدام إطار الكيان ، تمكنت من القيام بذلك بشيء من هذا القبيل:

var query = GetQueryable();
foreach (var tag in tags)
{
   query = query.Where(i => i.Tags.Contains(tag));
}

ومع ذلك ، لا يبدو أن هذا يعمل مع RavendB ، على الأرجح لأنه لا يوجد مدعوم .. لقد حاولت أيضًا إعادة كتابته باستخدام أي ، (Where(i => i.Tags.Any(t=>t == tag))) لكن هذا يعطيني استثناء غريب:

Unable to cast object of type
'System.Linq.Expressions.PrimitiveParameterExpression`1[System.String]'
to type 'System.Linq.Expressions.MemberExpression

أي أفكار عظيمة؟ هل أفعل هذا خطأً تمامًا؟

هل كانت مفيدة؟

المحلول

لا يتم دعمه في الواقع (ربما ينبغي أن يكون كذلك ، لكن هذه مسألة أخرى تمامًا - نضيف حقًا دعمًا لمختلف المشغلين عند طلبها)

أما بالنسبة للاستعلامات المتعددة ضد أي ، أفترض أنك تحاول القيام ببيانات ديناميكية وتريد تحقيق شيء مثل

"X OR Y OR Z"

هذا أمر صعب ، وسيقوم مزود LINQ بشكل افتراضي بتجميع تلك المتعددة حيث الجمل مع ، وبالتالي يبدو مثالك

"X AND Y AND Z"

من الواضح أنه لن يكون الأمر كذلك.

خيارك الأفضل لهذا الشخص هو النزول إلى استعلام Lucene (على الأقل في الوقت الحالي) والقيام بشيء مثل هذا:

var results = s.Advanced.LuceneQuery<Item>()
                   .Where(string.Format("Tags,:({0})", string.Join(" OR ", tags))); 

منطقي؟

سيبدو الاستعلام أعلاه شيئًا مثل

"Tags,:(X OR Y OR Z)"

ملاحظة: "العلامات" ، تقوم بإبلاغ Ravendb بأن العلامات عبارة عن صفيف

حسنًا ، [تحرير]!

أسهل طريقة للحصول على ما أنت بالفعل تريد هو القيام بشيء على هذا النحو

                new IndexDefinition<Item, Item>()
                {
                    Map = docs => from doc in docs
                                  select new
                                  {
                                      Tags = doc.Tags
                                  },
                    Indexes = {{ x => x.Tags, FieldIndexing.Analyzed }}
                }.ToIndexDefinition(store.Conventions));

ثم للاستعلام عنك ، يمكنك أن تفعل شيئًا كهذا:

                var results = s.Advanced.LuceneQuery<Item, WhateverYouCalledThatIndex>()
                   .Where(string.Format("Tags:({0})", string.Join(" AND ", tags)));

الآن ، أشياء يجب أن تكون على دراية بها

       Tags = doc.Tags

سوف يقوم بتسلسل هذا الصفيف بأكمله إلى نقطة عملاقة واحدة ، حيث إنها مجرد سلاسل ستعمل على هذا المثال.

أنا أتطلع إلى طرق أفضل للتعبير عن ذلك ، فمن غير المرجح أن نتوصل إلى طريقة LINQ -ish للقيام بذلك ، لأنها لا تخطط جيدًا حقًا - ولكنها هو إجابة ستعمل :)

أعتقد أنني أود أن أكون قادرًا على الأقل على القيام به

  Map = docs => from doc in docs
                                  select new
                                  {
                                      Tags = String.Join(" ", doc.Tags)
                                  },

(هذا لن ينجح ، لذلك لا تجربه) ، لكنه أكثر وضوحًا حول ما تريد تحقيقه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top