После того, как я недавно столкнулся с той же проблемой, я придумал следующее решение:
Сначала найдите все ItemTags, где tagName либо «смешно», либо «политика» и возвращает массив ItemTag _ids.
Затем найдите элементы, которые содержат все ItemTag _ids в массиве тегов
ItemTag
.find({ tagName : { $in : ['funny','politics'] } })
.lean()
.distinct('_id')
.exec((err, itemTagIds) => {
if (err) { console.error(err); }
Item.find({ tag: { $all: itemTagIds} }, (err, items) => {
console.log(items); // Items filtered by tagName
});
});
Хотя linq не предназначен для обновления списков неизменяемых данных, он очень удобен для получения элементов, которые вы хотите обновить. Я думаю, для вас это будет:
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).ToList().ForEach( trade => trade.Buy += optionQty);
Я не уверен, что это лучший способ, но он позволит вам обновить элемент из списка.
Тестовый объект:
public class SomeClass {
public int Value { get; set; }
public DateTime Date { get; set; }
}
Метод расширения:
public static class Extension {
public static void Update<T>(this T item, Action<T> updateAction) {
updateAction(item);
}
}
Тест:
public void Test()
{
// test data
List<SomeClass> list = new List<SomeClass>()
{
new SomeClass {Value = 1, Date = DateTime.Now.AddDays(-1)},
new SomeClass {Value = 2, Date = DateTime.Now },
new SomeClass {Value = 3, Date = DateTime.Now.AddDays(1)}
};
// query and update
(from i in list where i.Date.Day.Equals(DateTime.Now.Day) select i).First().Update(v => v.Value += 5);
foreach (SomeClass s in list) {
Console.WriteLine(s.Value);
}
}
Итак, вы ожидаете получить здесь единственный результат. В этом случае вы можете рассмотреть возможность использования метода SingleOrDefault
:
var record =
(from trade in CrudeBalancedList
where trade.Date.Month == monthIndex
select trade).SingleOrDefault();
if (record != null)
record.Buy += optionQty;
Обратите внимание, что метод SingleOrDefault
ожидает, что будет возвращено ровно одно или ноль значения (как и строка в таблице для некоторого уникального первичного ключа). Если возвращается более одной записи, метод вызовет исключение.
Чтобы создать такой метод, вы должны начать с его прототипа:
public static class UpdateEx {
public void Update(this IEnumerable<T> items,
Expression<Action> updateAction) {
}
}
Это простая часть.
Самая сложная часть будет заключаться в компиляции Expression
в оператор обновления SQL. В зависимости от того, какой синтаксис вы хотите поддерживать, сложность такого компилятора может варьироваться от тривиальной до невозможной.
Пример компиляции выражений Linq см. В классе TableQuery
проекта sqlite-net .