gpt4 book ai didi

asp.net-mvc - 在哪里/如何将 Solr 安装到 ASP.net MVC 应用程序中(使用 nHibernate/存储库模式)

转载 作者:行者123 更新时间:2023-12-04 01:21:59 25 4
gpt4 key购买 nike

我目前正在处理一个相当大的基于问题/答案的应用程序(有点像 stackoverflow/answerbag.com)
我们使用 SQL (Azure) 和 nHibernate 进行数据访问,使用 MVC 进行 UI 应用程序。

到目前为止,从我们有一个 的意义上说,模式大致与 stackoverflow 数据库一致。发帖 表(包含两个问题/答案)

可能会使用以下存储库界面的内容:

public interface IPostRepository
{
void PutPost(Post post);
void PutPosts(IEnumerable<Post> posts);

void ChangePostStatus(string postID, PostStatus status);

void DeleteArtefact(string postId, string artefactKey);
void AddArtefact(string postId, string artefactKey);

void AddTag(string postId, string tagValue);
void RemoveTag(string postId, string tagValue);

void MarkPostAsAccepted(string id);
void UnmarkPostAsAccepted(string id);

IQueryable<Post> FindAll();
IQueryable<Post> FindPostsByStatus(PostStatus postStatus);
IQueryable<Post> FindPostsByPostType(PostType postType);
IQueryable<Post> FindPostsByStatusAndPostType(PostStatus postStatus, PostType postType);
IQueryable<Post> FindPostsByNumberOfReplies(int numberOfReplies);
IQueryable<Post> FindPostsByTag(string tag);
}

我的问题是:
我在哪里/如何将 solr 放入这个以更好地查询这些“帖子”
(我将使用 solrnet 与 Solr 进行实际通信)

理想情况下,我将 SQL db 仅用作持久存储 -
大部分上述 IQueryable 操作将进入某种 SolrFinder 类(或类似的东西)

Body 属性是当前导致问题的属性 - 它相当大,并且会减慢对 sql 的查询速度。

我的主要问题是,例如,如果有人“更新”了一个帖子——例如,添加了一个新标签,那么整个帖子将需要重新索引。
显然,这样做需要这样的查询:

"SELECT * FROM POST WHERE ID = xyz"



这当然会非常缓慢。
Solrnet 有一个 nHibernate 工具——但我相信这会和上面的结果一样吗?

我想了一个方法来解决这个问题,我想请教您的意见:
  • 将 ID 添加到队列(亚马逊 sqs 或其他东西 - 我喜欢它的易用性)
  • 在某处有一个服务(或一堆服务)可以执行上述查询,构建文档,然后将其重新添加到 solr。

  • 我的设计遇到的另一个问题:
    应该从哪里调用“重新索引”方法?
    MVC Controller ?或者我应该有一个“PostService”类型的类来包装 IPostRepository 的实例吗?

    关于这一点的任何指示都非常受欢迎!

    最佳答案

    在我工作的电子商务网站上,我们使用 Solr 提供产品目录的快速分面和搜索。 (在非 Solr 极客术语中,这意味着“ATI 卡 (34)、NVIDIA (23)、英特尔 (5)”样式的导航链接,您可以使用它们在 Zappos、Amazon、 NewEgg 和 Lowe's。)

    这是因为 Solr 旨在快速而良好地做这种事情,而试图在传统的关系数据库中有效地做这种事情是不会发生的,除非你想开始在数据库上添加和删除索引飞和去完整的 EAV,这只是咳 Magento 咳愚蠢。所以我们的 SQL Server 数据库是“权威”数据存储,而 Solr 索引是该数据的只读“投影”。

    到目前为止,您和我在一起是因为听起来您处于类似的情况。下一步是确定 Solr 索引中的数据可能稍微陈旧是否可以。你可能已经接受了它会有些陈旧的事实,但接下来的决定是

  • 陈旧有多陈旧?
  • 我什么时候重视速度或查询功能而不是陈旧?

  • 例如,我有一个我称之为“Worker”的东西,它是一个使用 Quartz.NET 的 Windows 服务。执行 C# IJob定期实现。每 3 小时,其中一项被执行的作业是 RefreshSolrIndexesJob ,而该工作所做的只是 ping HttpWebRequest转至 http://solr.example.com/dataimport?command=full-import .这是因为我们使用了 Solr 的内置 DataImportHandler实际从 SQL 数据库中吸取数据;该作业只需要定期“触摸”该 URL 即可使同步工作。因为 DataImportHandler 定期提交更改,所以这一切都在后台有效运行,对网站用户透明。

    这确实意味着产品目录中的信息最多可能会过时 3 小时。用户可能会在目录页面上单击“Medium In Stock (3)”链接(因为这种分面数据是通过查询 SOLR 生成的),但随后在产品详细信息页面上看到没有介质库存(从页面,数量信息是少数没有缓存和直接针对数据库查询的信息之一)。这很烦人,但在我们的特定场景中通常很少见(我们是一家相当小的企业,流量不是那么高),无论如何,当我们重新从头重建整个索引时,它会在 3 小时内修复,所以我们接受了这一点作为一个合理的权衡。

    如果你能接受这种程度的“陈旧”,那么这个后台工作进程是一个不错的选择。您可以采用“每隔几个小时重新构建整个事物”的方法,或者您的存储库可以将 ID 插入表中,例如 dbo.IdentitiesOfStuffThatNeedsUpdatingInSolr ,然后如果考虑到数据集的大小或复杂性,定期从头开始重建整个索引是不合理的,那么后台进程可以定期扫描该表并仅更新 Solr 中的那些文档。

    第三种方法是让您的存储库产生一个后台线程,该线程或多或少地同时更新与当前文档有关的 Solr 索引,因此数据只会过时几秒钟:
    class MyRepository
    {
    void Save(Post post)
    {
    // the following method runs on the current thread
    SaveThePostInTheSqlDatabaseSynchronously(post);

    // the following method spawns a new thread, task,
    // queueuserworkitem, whatevever floats our boat this week,
    // and so returns immediately
    UpdateTheDocumentInTheSolrIndexAsynchronously(post);
    }
    }

    但是,如果由于某种原因而爆炸,您可能会错过 Solr 中的更新,因此让 Solr 定期“将其全部清除并刷新”仍然是一个好主意,或者使用收割机后台工作人员类型的服务来检查是否存在- Solr 中的最新数据,每个人都有一次在蓝色的月亮。

    至于从 Solr 查询这些数据,您可以采用几种方法。一种是隐藏 Solr 完全通过 Repository 的方法存在的事实。我个人不建议这样做,因为您的 Solr 架构很可能会针对将访问该数据的 UI 进行无耻的定制;我们已经决定使用 Solr 来提供简单的分面、排序和快速显示信息,所以我们不妨充分利用它。这意味着当我们打算访问 Solr 以及我们打算访问最新的、非缓存的数据库对象时,在代码中使其明确。

    就我而言,我最终使用 NHibernate 进行 CRUD 访问(加载 ItemGroup ,对其定价规则进行测试,然后将其保存回来),放弃存储库模式,因为我通常不会在 NHibernate 和它的映射已经对数据库进行了抽象。 (这是个人选择。)

    但是在查询数据时,我很清楚我是将它用于面向目录的目的(我关心速度和查询)还是用于在后端管理应用程序的表中显示(我关心货币)。为了在网站上查询,我有一个接口(interface)叫 ICatalogSearchQuery .它有一个 Search()接受 SearchRequest 的方法我在这里定义了一些参数——选定的方面、搜索词、页码、每页的项目数等——并返回 SearchResult -- 剩余方面、结果数量、此页面上的结果等。非常无聊的东西。

    有趣的是, ICatalogSearchQuery 的实现正在使用 ICatalogSearchStrategy 的列表在下面。默认策略, SolrCatalogSearchStrategy , 通过一个简单的老式 HttpWebRequest 直接命中 SOLR并解析 HttpWebResponse 中的 XML (恕我直言,这比某些 SOLR 客户端库更容易使用,尽管自一年多前我上次查看它们以来它们可能已经变得更好)。如果该策略由于某种原因引发异常或呕吐,则 DatabaseCatalogSearchStrategy直接命中SQL数据库——尽管它忽略了 SearchRequest的一些参数,就像分面或高级文本搜索一样,因为这样做效率低下,这也是我们首先使用 Solr 的全部原因。这个想法是,通常 SOLR 会在功能齐全的情况下快速回答我的搜索请求,但是如果出现问题并且 SOLR 出现故障,那么站点的目录页面仍然可以通过点击数据库以“缩减功能模式”运行一个有限的功能集直接。 (由于我们在代码中明确表示这是一个搜索,该策略可以在忽略某些搜索参数方面有一定的自由度,而不必担心对客户端的影响太严重。)

    关键外卖:重要的是,对可能陈旧的数据存储还是权威数据存储执行查询的决定已经明确——如果我想要快速、可能陈旧的具有高级搜索功能的数据,我使用 ICatalogSearchQuery .如果我想要具有插入/更新/删除功能的缓慢的最新数据,我会使用 NHibernate 的命名查询(或在您的情况下使用存储库)。如果我对 SQL 数据库进行更改,我知道进程外 Worker 服务最终会更新 Solr,从而使事情最终保持一致。 (如果某些事情真的很重要,我可以广播一个事件或直接 ping SOLR 存储,告诉它更新,如果必须的话,可能在后台线程中。)

    希望能给你一些见解。

    关于asp.net-mvc - 在哪里/如何将 Solr 安装到 ASP.net MVC 应用程序中(使用 nHibernate/存储库模式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3672605/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com