如何进行查询以返回包含列表中所有 id 的对象

Posted

技术标签:

【中文标题】如何进行查询以返回包含列表中所有 id 的对象【英文标题】:How can I make a query that returns objects who contain all ids from list 【发布时间】:2015-10-29 10:51:49 【问题描述】:

我有两个对象:配置文件和标签。每个配置文件可以包含多个标签。在我的搜索页面上,我可以选择多个标签进行搜索。现在我想要一个查询来获取具有所有选定标签的所有配置文件。

因此,如果我使用WhereRestrictionOn().IsIn(),我会得到至少包含 1 个标签的配置文件,但我需要返回包含列表中所有标签的配置文件。

我还为每个选定的标签尝试了多个 Where 条件,但我根本没有得到任何结果。

我不知道如何做到这一点,非常感谢任何帮助!

结构:

个人资料:ID

ProfileTag : ProfileId, TagId

标签:ID

映射配置文件

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Agrolink.Application.Models" assembly="Agrolink.Application">
  <class name="Agrolink.Application.Models.Profile" lazy="false" table="Profiles" >

    <id name="Id" column="Id"  >
      <generator class="identity" />
    </id>

    <bag name="Tags" table="ProfileTags" cascade="all-delete-orphan" inverse="true">
      <key column="IdProfile" not-null="true"/>
      <one-to-many class="Agrolink.Application.Models.ProfileTag"  />
    </bag>

  </class>
</hibernate-mapping>

映射 ProfileTag

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Agrolink.Application.Models" assembly="Agrolink.Application">
  <class name="Agrolink.Application.Models.ProfileTag" lazy="false" table="ProfileTags" >

    <id name="Id" column="Id"  >
      <generator class="identity" />
    </id>

    <many-to-one name="Profile" class="Agrolink.Application.Models.Profile" column="IdProfile" cascade="save-update" />
    <many-to-one name="Tag" class="Agrolink.Application.Models.Tag" column="IdTag" cascade="none" />

  </class>
</hibernate-mapping>

映射标签

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Agrolink.Application.Models" assembly="Agrolink.Application">
  <class name="Agrolink.Application.Models.Tag" lazy="false" table="Tags" >

    <id name="Id" column="Id"  >
      <generator class="identity" />
    </id>

    <property name="Name" column="Name" />
    <property name="Type"  type="Agrolink.Application.Models.TagType, Agrolink.Application"  column="IdType" />

    <many-to-one name="Parent" class="Agrolink.Application.Models.Tag" column="IdParent" cascade="none" />

    <bag name="Children" table="Tags" cascade="all" inverse="true">
      <key column="IdParent" not-null="true"/>
      <one-to-many class="Agrolink.Application.Models.Tag"  />
    </bag>

  </class>
</hibernate-mapping>

SubQuery 来实现这个(解决方案):

        Profile p = null;
        Account a = null;
        Institute i = null;

        var q = Session.QueryOver(() => p)
            .JoinAlias(x => x.Account, () => a)
            .JoinAlias(x => x.Institute, () => i)
            .Where(x => x.Type == ProfileType.Expert && x.Status == ProfileStatus.Active);

        if(_keywordIds.Any())
            foreach (var keywordId in _keywordIds)
            
                Tag t = null;

                var subQ = QueryOver.Of<ProfileTag>()
                    .JoinAlias(pt => pt.Tag, () => t)
                    .Where(() => t.Id == keywordId)
                    .Select(pt => pt.Profile.Id);           

                q.WithSubquery.WhereProperty(() => p.Id).In(subQ);
            

        if (_institute != null) q.Where(() => i.Id == _institute);

        if (!string.IsNullOrEmpty(_name)) q.Where(Restrictions.Disjunction()
                    .Add(Restrictions.Like("a.FirstName", _name + "%"))
                    .Add(Restrictions.Like("a.LastName", _name + "%"))
                );

        return (PagedList<Profile>) q.List<Profile>().ToPagedList(_page, _itemsPerPage);

【问题讨论】:

你需要一个子查询。检查这个***.com/q/23772548/1679310 这看起来不错@RadimKöhler,但我在这行遇到问题:query.WithSubquery .WhereProperty(() => file.id) .In(subQueryForAttribute);我不确定在 WhereProperty 中放什么。对象结构有问题。 @RadimKöhler 我的映射与您链接我的示例几乎相同。我也可以在问题中添加它。 哇,那是完全不同的场景。这不是多对多 - 你有 “正确的映射” ...所以它应该很容易......如果你仍然认为你不能使用那个解决方案,我会尝试起草那... 我在答案中发布了我的查询。你能检查一下吗?谢谢! 【参考方案1】:

差不多了,但我们需要所谓的 Detached QueryOver,我们将通过构造 QueryOver.Of 获得它

foreach (var keywordId in _keywordIds)

    //Tag t = null;

    var subQ = QueryOver.Of<ProfileTag>()
        //.JoinAlias(pt => pt.Tag, () => t)
        //.Where(() => t.Id == keywordId)
        .Where(x => x.Tag.Id == keywordId)
        //.Select(pt => t.Id);           
        .Select(pt => pt.Profile.Id);          

    q.WithSubquery.WhereProperty(() => p.Id).In(subQ);

【讨论】:

嗯,我还是有问题。它没有返回任何结果。我似乎在子查询的 Select 上得到了一个空异常。 您能分享一下您最近的尝试吗?调整问题 更新了相关子查询。 我在本地尝试过,用我的实体(以可行的方式替换你的)和更新的 foreach ......它应该可以工作 是的!我也弄清楚出了什么问题。非常感谢大家的帮助!

以上是关于如何进行查询以返回包含列表中所有 id 的对象的主要内容,如果未能解决你的问题,请参考以下文章

休眠从对象中延迟获取嵌套列表

对象化查询以返回属性值列表

如何将返回的字典变成一个大列表?

如何构建和查询 Room DB 以返回多个类的对象列表?

如何返回具有特定字段值的所有数据库行

求助啊,tp下,mongodb如何查询后只返回某个字段值